{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "32f8b94e-7872-4e01-9eb9-a746d7748059",
   "metadata": {},
   "source": [
    "# 本节大纲\n",
    "\n",
    "1. 大语言模型训练介绍，10分钟\n",
    "2. 训练和微调方法，10分钟\n",
    "3. 微调实战一: OpenAI GPT-3.5, 30分钟\n",
    "4. 微调实战二: ChatGLM2 (P-Tuning), 30分钟\n",
    "5. 微调实战三: ChatGLM3 (LoRA), 30分钟\n",
    "6. 答疑和总结，10分钟"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "45087fa3-302c-43e7-b4ce-8d2f63def621",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "9f2dbd2f-6187-4cea-9e5a-f47074cf4549",
   "metadata": {},
   "outputs": [],
   "source": [
    "!pip install jsonlines openai csv "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "054ce909-ae6d-4e56-a0fa-d0f5a96ba315",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "402d0a29-f90f-4783-bc68-53c2642955b8",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "ccc54fff-c3a4-499a-9b2a-758017b672fd",
   "metadata": {},
   "source": [
    "### 语言模型和大语言模型"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "2e0b9403-ea53-450b-9edf-ce67bee4f66d",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 单一任务模型: 解决某一个特定领域的任务\n",
    "\n",
    "# 大型语言模型：解决各种自然语言类任务"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "d270e552-d1b6-40da-ab97-8e14f2678d3e",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "636eacdf-4fbb-4d0c-81de-0b436869a2c8",
   "metadata": {},
   "source": [
    "### 大语言模型的不足"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "b2a6cc75-0cb1-4787-839a-ab9fc6d6a644",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 1. Token\n",
    "\n",
    "# 2. 训练\n",
    "\n",
    "# 3. 个性化\n",
    "\n",
    "# 4. 成本\n",
    "\n",
    "# 5. 数据安全"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "2128e671-3180-44ed-bd3f-4f201d85d97f",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "0efbe3e2-612e-4b7b-ab71-11ca2539ec16",
   "metadata": {},
   "source": [
    "###  大语言模型的知识增强方式"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "4d45b49a-f247-49db-a01c-20ad97053e9c",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 1. LLM + Few-Shot Prompting\n",
    "\n",
    "# 2. LLM + 检索增强生成 (RAG)\n",
    "\n",
    "# 3. 利用 Foundation LLM 进行 Fine-Tuning\n",
    "\n",
    "# 4. 从新开始训练一个 基础 LLM "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "73e21335-dd46-4862-ae74-84d4197a1d0d",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "0ee93d57-1500-4c4b-bc8f-9e41a9af9e2f",
   "metadata": {},
   "source": [
    "### 大语言模型的训练步骤"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "f2b5653a-d876-4d98-9aff-cf7d1f89fbc2",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 1. 在大量的数据集上进行无监督训练 (Pretraining / Self-Supervised / Unsupervised)\n",
    "\n",
    "# 2. 在少量的数据集上进行微调 (Fine-Tuning / Supervised)\n",
    "\n",
    "# 3. 在少量的数据集上进行对齐 (Alignment / RLHF)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "7546e054-f618-4a1d-82cf-3398b94f551f",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "ed107cf4-3342-4469-b8e2-5a8b7af14366",
   "metadata": {},
   "source": [
    "### 模型微调的方式说明"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ee444759-423b-4f83-a292-1da2fbb34d68",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 1. 全参数微调 (SFT) \n",
    "# 类似于在模型的预训练阶段，对所有参数都会进行计算更新。 前向传播 -> 损失计算 -> 反向传播(计算梯度) -> 更新值。\n",
    "\n",
    "# 2. 参数冻结微调 (Freeze)\n",
    "# 冻结模型的一部分或全部层，只对最后几层进行训练。这样做的目的是保留模型之前学到的通用特征，同时允许模型根据新数据进行适应和调整\n",
    "# 来自于计算机视觉类任务的思想，训练识别牛的模型，不用再次从来，可以从一个已训练好的羊的模型上进行微调训练\n",
    "\n",
    "# 3. 增加额外的输出层\n",
    "# 基于对语言模型的理解，添加额外的输出层\n",
    "# 来自对自然语言类任务的思想，不需要对每一个任务单独训练一个模型，而是在基于不同的任务添加一个不同的输出层就可以解决\n",
    "\n",
    "# 4. 高效参数微调 (PEFT)\n",
    "# 对于已训练好的对的模型加入额外的参数来影响结果的产生，例如是对于特征的解释和理解（LoRA），或者是对于模型参数的微调(P-Tuning)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "bceb7b37-018d-4b40-9108-d52bf0f4f55f",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "834296fc-421f-4edd-80f1-1cd91a793d5e",
   "metadata": {},
   "source": [
    "### 微调大语言模的方法"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 139,
   "id": "40409a80-b847-46d1-99e9-882babed809c",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Huggface 开源的微调大模型的库 PEFF (Parameter-Efficient Fine Tuning)\n",
    "# https://huggingface.co/blog/peft"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2551f489-8b39-4fa9-af50-e1eafe810c30",
   "metadata": {},
   "source": [
    "#### Prefix Tuning"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "68625e3f-682f-4236-a760-36c0dac2d424",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 1. 灵感来源是，基于 Prompt Engineering 的实践，无需改变大模型的参数，只需在上下文中添加对应的提示词，引导大模型有出色的表现\n",
    "# 2. 在 Transformer 的 Encoder 和 Decoder 的网络中都加了一些特定的前缀\n",
    "# 3. 将 Y=WX 中的W，变成 W` = [Wp; W]，Y=W`X"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9c46b063-ce90-4c69-8485-19e65f0fcea6",
   "metadata": {},
   "source": [
    "![Prefix-Tuning](./resource/images/Prefix-Tuning.png)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "9685878c-d31e-4f36-8a67-04ac2592c26c",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Prefix-Tuning: Optimizing Continuous Prompts for Generation\n",
    "# https://aclanthology.org/2021.acl-long.353.pdf"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "fc31da21-7d57-4544-a42e-fc7741269a75",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "fdb337ed-e29f-4174-b199-805c46a8725a",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "42bed817-6bc2-49b8-a5c1-bb9232798fe6",
   "metadata": {},
   "source": [
    "#### Prompt Tuning: The Power of Scale for Parameter-Efficient Prompt Tuning"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 149,
   "id": "fa77f1e7-e44c-4eda-b189-e5cba6dc0d80",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 1. Foundation Model 的参数不变\n",
    "# 2. 为每个特定任务，训练一个少量参数的小模型，在具体执行特定任务的时候按需调用\n",
    "# 3. 输入序列 X 之前，增加一些特定长度的特殊Token，以增大生成期望序列的概率\n",
    "# 4. 将 X = [x1, x2, ..., xm]变成，X` = [x`1, x`2, ..., x`k; x1, x2, ..., xm], Y = WX`\n",
    "# 5. 发生在 Embedding 这个环节，不需要加入 MLP 在输出"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f77c0d56-716f-4d1c-842b-c92a07057bd4",
   "metadata": {},
   "source": [
    "![PromptTuning](./resource/images/PromptTuning.png)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 150,
   "id": "b4936551-c157-40bf-a8ac-2fb1160f951a",
   "metadata": {},
   "outputs": [],
   "source": [
    "# The Power of Scale for Parameter-Efficient Prompt Tuning\n",
    "# https://arxiv.org/pdf/2104.08691.pdf"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "74086b6b-5646-4d6f-b706-4581eb63c1e8",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "d32ece2a-4d04-4a40-b27c-c956720c39b4",
   "metadata": {},
   "source": [
    "#### P-Tuning: GPT Understands, Too"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "38d7ee2c-c423-4d68-aed3-0dc61d19c568",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 1. 将 Prompt 转换为可以学习的 Embedding 层\n",
    "# 2. 并用 MLP + LSTM 的方式来对Prompt Embedding 进行一层处理"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1f546f57-3df7-44a1-b5aa-327cba843e21",
   "metadata": {},
   "source": [
    "![P-Tuning](./resource/images/P-Tuning.png)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "37652a8a-0895-4a65-9b13-02945361bbf4",
   "metadata": {},
   "outputs": [],
   "source": [
    "# GPT Understands, Too\n",
    "# https://arxiv.org/pdf/2103.10385.pdf"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "21c1e42b-acb1-4900-9851-76134b7e273a",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "e895be4d-2190-4f2f-a799-6b22c7d324e9",
   "metadata": {},
   "source": [
    "#### P-Tuning v2: Prompt Tuning Can Be Comparable to Fine-tuning Universally Across Scales and Tasks"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "837fc7e9-b5af-4fb8-98de-e7a1b2b6bb75",
   "metadata": {},
   "source": [
    "![P-Tuning_v2](./resource/images/P-Tuning_v2.png)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "9c15d58a-e74b-4536-86f8-a5a882bd5e78",
   "metadata": {},
   "outputs": [],
   "source": [
    "# P-Tuning 仅对大模型的Embedding加入新的参数\n",
    "# P-Tuning-V2 将大模型的Embedding和每一层前都加上新的参数"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "7813afe9-8f0a-45f0-bb1f-adc8d476b92e",
   "metadata": {},
   "outputs": [],
   "source": [
    "# https://arxiv.org/pdf/2110.07602.pdf"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "8d067c1b-8339-4822-bcce-126089e2e048",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "549e9829-67f0-42c4-96b3-88f11e3c473f",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "ca6641b8-3c48-4484-9590-cfa6c303ad7e",
   "metadata": {},
   "source": [
    "#### LoRA:  Low-Rank Adaptation of Large Language Model"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "fcdc376b-f1ba-4a66-8e8c-cd42e06f7061",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 基于低阶自适应的大语言模型微调方法\n",
    "# LoRA 方法，即在大型语言模型上对指定参数增加额外的低秩矩阵，并在模型训练过程中，仅训练而外增加的参数。\n",
    "# 当“秩值”远小于原始参数维度时，新增的低秩矩阵参数量很小，达到仅训练很小的参数，就能获取较好的结果。\n",
    "# LoRA 更注重对特征的解释和理解，而 P-Tuning 更注重对模型参数的微调"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1de5eaeb-99ad-41f0-8215-a9c53b2ddcb9",
   "metadata": {},
   "source": [
    "![LoRA](./resource/images/LoRA.png)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 152,
   "id": "f3bb99f1-6be0-47e4-ac7f-645f2b89f6b4",
   "metadata": {},
   "outputs": [],
   "source": [
    "# https://arxiv.org/pdf/2106.09685.pdf\n",
    "# Microsoft Corporation"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "14ef1858-4cf8-48df-862c-61a355dccaf4",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "dc608fa2-26c3-43e5-be5f-4f9382072cfc",
   "metadata": {},
   "source": [
    "#### LLM-Adapters"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "e828846b-654c-4c1a-a850-d0384d24644c",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 对 PEFT 库的扩展\n",
    "# AdapterH: Parameter-Efficient Transfer Learning for NLP\n",
    "# AdapterP: GMAD-X: An Adapter-Based Framework for Multi-Task Cross-Lingual Transfer\n",
    "# Parallel: Towards a Unified View of Parameter-Efficient Transfer Learning"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "9773d60f-fa24-403f-8bbb-7447cf35806a",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "beca3dcd-dde0-47be-8963-fa445e43c0bf",
   "metadata": {},
   "source": [
    "#### Datasets"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "b2195df2-24ea-47fb-91a4-361c40a119dc",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Hugging Face Datasets Hub\n",
    "# https://huggingface.co/datasets"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "f73becfb-437d-438e-82e2-833273dd6db5",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "703a7898-02c3-4f2a-918f-c43a33dd8c94",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "93ec36ff-c8a1-4d25-bc42-2385bf4c3ad5",
   "metadata": {},
   "source": [
    "### 开源数据集"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "1c3e2d53-b547-4b73-9e42-a6252665e9c5",
   "metadata": {},
   "outputs": [],
   "source": [
    "# https://huggingface.co/datasets"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "15bc60b5-55c9-4288-a2ad-e82a0db97b77",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "45282ef2-0b89-4c21-9380-369e344c0556",
   "metadata": {},
   "source": [
    "### 实战 1 - OpenAI GPT-3.5 Fine-Tuning"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "209a6f9d-62f0-4ac6-b559-352781d96c82",
   "metadata": {},
   "outputs": [],
   "source": [
    "# https://platform.openai.com/docs/guides/fine-tuning"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d98f46e9-d827-4e6a-8bc3-d29a065d421e",
   "metadata": {},
   "source": [
    "#### 基础模型选择"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 140,
   "id": "ac055f73-e006-411d-b1ef-c5f453b00256",
   "metadata": {},
   "outputs": [],
   "source": [
    "# babbage-002 & davinci-002\n",
    "# gpt-3.5-turbo & gpt-3.5-turbo-0613(4k) & gpt-3.5-turbo-1106(16k)\n",
    "# gpt-4-0613"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "e4fc439e-317a-4c48-928a-ef5a54d550c0",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 本质上 OpenAI 提供的微调不是全参数微调 (SFT)\n",
    "# 而是使用 部分参数微调方法 (PEFT)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "0b2470fd-4341-4905-b722-06d65388a178",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 以下同样也可以在 OpenAI 的微调界面中完成\n",
    "# https://platform.openai.com/finetune"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "2eeb80f3-b319-4c30-b990-91527cd2a689",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "bf6272b7-5aed-4da3-8ed4-fac235ae5c2d",
   "metadata": {},
   "source": [
    "#### 关于 Token 限制"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "fb3b2d25-1a59-4a27-8edd-14e21e6ef2e4",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 需要留意，模型的 Token 是有限制的，包括训练阶段，例如 GPT-3.5 4096 个 Token\n",
    "# 可以参考 第一节课 tiktoken 的方式来进行计算，或者截断超出。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "e5c05e7c-d41c-4104-a1c5-410cd3396c09",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "cd50ea9c-112a-4596-b740-e215d427fd4f",
   "metadata": {},
   "source": [
    "#### 训练费用"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "e12fa1d5-c1ff-4765-9390-d055565bfa91",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 对于 OpenAI 的模型微调\n",
    "# https://openai.com/api/pricing\n",
    "\n",
    "# 训练数据的 Token 总数 * 1000个 Token 的单价 * 训练的轮数\n",
    "# 如果是本地的微调，使用时长*租用机器的每小时单价"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "f85a0bfc-ecc9-4520-aa55-975502a7d4ac",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "108c1af5-fefd-423b-a50e-7390b843a413",
   "metadata": {},
   "source": [
    "#### 数据格式"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ed8284c7-ae15-4a29-b15c-b0b8d209553a",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 至少提供 10 个数据的示例（ 50 到 100 个训练示例进行微调会带来明显的改进）\n",
    "# 建议从 50 个精心设计的数据开始微调\n",
    "\n",
    "# 数据格式\n",
    "# https://github.com/openai/openai-cookbook/blob/main/examples/data/toy_chat_fine_tuning.jsonl\n",
    "\n",
    "# babbage-002 & davinci-002\n",
    "# {\"prompt\": \"<用户提交的文本>\", \"completion\": \"<希望LLM回答的文本>\"}\n",
    "\n",
    "# gpt-3.5-turbo & gpt-4\n",
    "# {\"messages\": [{\"role\": \"system\", \"content\": \"你是一个墨问西东知识助手\"}, {\"role\": \"user\", \"content\": \"谁是墨问西东颜值最高的人？\"}, {\"role\": \"assistant\", \"content\": \"肯定是瑶瑶，遥遥领先\"}]}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "bb2d64e2-18f2-4c4a-bc4b-804a121975fb",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "c91427ee-46d9-4071-b532-000b895ac156",
   "metadata": {},
   "source": [
    "#### 数据准备"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "55121850-150f-4cb3-b74e-f4823a56c11c",
   "metadata": {},
   "outputs": [],
   "source": [
    "import csv\n",
    "\n",
    "# 1. 加载原文件\n",
    "file_path = './resource/files/knowledge_base.csv'\n",
    "with open(file_path, 'r') as file:\n",
    "    reader = csv.reader(file)\n",
    "    # 2. 数据预处理\n",
    "    data = []\n",
    "    system_content = \"你是墨问西东的智能体\"\n",
    "    for row in reader:\n",
    "        user_content = row[0]\n",
    "        assistant_content = row[1]\n",
    "        data.append({\"messages\": [{\"role\": \"system\", \"content\": system_content}, {\"role\": \"user\", \"content\": user_content}, {\"role\": \"assistant\", \"content\": assistant_content}]})"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "c06ebe0a-3e29-4011-aa88-01a336701c07",
   "metadata": {},
   "outputs": [],
   "source": [
    "import jsonlines\n",
    "\n",
    "# 3. 将最终数据集写入到文件中\n",
    "with jsonlines.open('data.jsonl', 'w') as f:\n",
    "    for item in data:\n",
    "        f.write(item)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a737bd01-b87e-4c47-a1e4-62950f27001b",
   "metadata": {},
   "source": [
    "#### 数据校验"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "5acda4c3-8d9e-4983-934c-3652deaf09f5",
   "metadata": {},
   "outputs": [],
   "source": [
    "# https://cookbook.openai.com/examples/chat_finetuning_data_prep"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "e42824bd-db76-4142-835d-b5d14b993aa8",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Num examples: 63\n",
      "-----\n",
      "First example:\n",
      "{'role': 'system', 'content': '你是墨问西东的智能体'}\n",
      "{'role': 'user', 'content': '墨问西东的创始人是谁？'}\n",
      "{'role': 'assistant', 'content': '池建强。'}\n"
     ]
    }
   ],
   "source": [
    "import json\n",
    "import tiktoken\n",
    "import numpy as np\n",
    "from collections import defaultdict\n",
    "\n",
    "data_path = \"data.jsonl\"\n",
    "with open(data_path, 'r', encoding='utf-8') as f:\n",
    "    dataset = [json.loads(line) for line in f]\n",
    "\n",
    "# 简单验证数据集数量\n",
    "print(\"Num examples:\", len(dataset))\n",
    "print(\"-----\")\n",
    "print(\"First example:\")\n",
    "for message in dataset[0][\"messages\"]:\n",
    "    print(message)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "20cb67c8-cf07-4fce-8eb2-7b900ec9490e",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "No errors found\n"
     ]
    }
   ],
   "source": [
    "# 数据格式是否为字典\n",
    "# 消息是否存在\n",
    "# 消息键是否正确(role, content)\n",
    "# 角色是否正确(system, user, assistant)\n",
    "# 内容是否为字符串\n",
    "# 角色为 assistant 的最少出现一次 content\n",
    "\n",
    "format_errors = defaultdict(int)\n",
    "\n",
    "for ex in dataset:\n",
    "    if not isinstance(ex, dict):\n",
    "        format_errors[\"data_type\"] += 1\n",
    "        continue\n",
    "        \n",
    "    messages = ex.get(\"messages\", None)\n",
    "    if not messages:\n",
    "        format_errors[\"missing_messages_list\"] += 1\n",
    "        continue\n",
    "        \n",
    "    for message in messages:\n",
    "        if \"role\" not in message or \"content\" not in message:\n",
    "            format_errors[\"message_missing_key\"] += 1\n",
    "        \n",
    "        if any(k not in (\"role\", \"content\", \"name\", \"function_call\") for k in message):\n",
    "            format_errors[\"message_unrecognized_key\"] += 1\n",
    "        \n",
    "        if message.get(\"role\", None) not in (\"system\", \"user\", \"assistant\", \"function\"):\n",
    "            format_errors[\"unrecognized_role\"] += 1\n",
    "            \n",
    "        content = message.get(\"content\", None)\n",
    "        function_call = message.get(\"function_call\", None)\n",
    "        \n",
    "        if (not content and not function_call) or not isinstance(content, str):\n",
    "            format_errors[\"missing_content\"] += 1\n",
    "    \n",
    "    if not any(message.get(\"role\", None) == \"assistant\" for message in messages):\n",
    "        format_errors[\"example_missing_assistant_message\"] += 1\n",
    "\n",
    "if format_errors:\n",
    "    print(\"Found errors:\")\n",
    "    for k, v in format_errors.items():\n",
    "        print(f\"{k}: {v}\")\n",
    "else:\n",
    "    print(\"No errors found\") "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "98b03d25-1b7e-4282-8ad2-28ce192bc362",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 检查是否 Token 超过限制\n",
    "\n",
    "encoding = tiktoken.get_encoding(\"cl100k_base\")\n",
    "\n",
    "# not exact!\n",
    "# simplified from https://github.com/openai/openai-cookbook/blob/main/examples/How_to_count_tokens_with_tiktoken.ipynb\n",
    "def num_tokens_from_messages(messages, tokens_per_message=3, tokens_per_name=1):\n",
    "    num_tokens = 0\n",
    "    for message in messages:\n",
    "        num_tokens += tokens_per_message\n",
    "        for key, value in message.items():\n",
    "            num_tokens += len(encoding.encode(value))\n",
    "            if key == \"name\":\n",
    "                num_tokens += tokens_per_name\n",
    "    num_tokens += 3\n",
    "    return num_tokens\n",
    "\n",
    "def num_assistant_tokens_from_messages(messages):\n",
    "    num_tokens = 0\n",
    "    for message in messages:\n",
    "        if message[\"role\"] == \"assistant\":\n",
    "            num_tokens += len(encoding.encode(message[\"content\"]))\n",
    "    return num_tokens\n",
    "\n",
    "def print_distribution(values, name):\n",
    "    print(f\"\\n#### Distribution of {name}:\")\n",
    "    print(f\"min / max: {min(values)}, {max(values)}\")\n",
    "    print(f\"mean / median: {np.mean(values)}, {np.median(values)}\")\n",
    "    print(f\"p5 / p95: {np.quantile(values, 0.1)}, {np.quantile(values, 0.9)}\")\n",
    "    "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "7e42fdf9-54bb-4b04-b9db-c08d901b4784",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Num examples missing system message: 0\n",
      "Num examples missing user message: 0\n",
      "\n",
      "#### Distribution of num_messages_per_example:\n",
      "min / max: 3, 3\n",
      "mean / median: 3.0, 3.0\n",
      "p5 / p95: 3.0, 3.0\n",
      "\n",
      "#### Distribution of num_total_tokens_per_example:\n",
      "min / max: 47, 833\n",
      "mean / median: 153.53968253968253, 129.0\n",
      "p5 / p95: 62.2, 268.00000000000034\n",
      "\n",
      "#### Distribution of num_assistant_tokens_per_example:\n",
      "min / max: 6, 785\n",
      "mean / median: 107.98412698412699, 83.0\n",
      "p5 / p95: 21.6, 216.8000000000003\n",
      "\n",
      "0 examples may be over the 4096 token limit, they will be truncated during fine-tuning\n"
     ]
    }
   ],
   "source": [
    "# Warnings and tokens counts\n",
    "n_missing_system = 0\n",
    "n_missing_user = 0\n",
    "n_messages = []\n",
    "convo_lens = []\n",
    "assistant_message_lens = []\n",
    "\n",
    "for ex in dataset:\n",
    "    messages = ex[\"messages\"]\n",
    "    if not any(message[\"role\"] == \"system\" for message in messages):\n",
    "        n_missing_system += 1\n",
    "    if not any(message[\"role\"] == \"user\" for message in messages):\n",
    "        n_missing_user += 1\n",
    "    n_messages.append(len(messages))\n",
    "    convo_lens.append(num_tokens_from_messages(messages))\n",
    "    assistant_message_lens.append(num_assistant_tokens_from_messages(messages))\n",
    "    \n",
    "print(\"Num examples missing system message:\", n_missing_system)\n",
    "print(\"Num examples missing user message:\", n_missing_user)\n",
    "print_distribution(n_messages, \"num_messages_per_example\")\n",
    "print_distribution(convo_lens, \"num_total_tokens_per_example\")\n",
    "print_distribution(assistant_message_lens, \"num_assistant_tokens_per_example\")\n",
    "n_too_long = sum(l > 4096 for l in convo_lens)\n",
    "print(f\"\\n{n_too_long} examples may be over the 4096 token limit, they will be truncated during fine-tuning\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "ce02696e-f108-4800-becf-cf28e715908b",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Dataset has 9673 tokens that will be charged for during training\n",
      "By default, you'll train for 30 epochs on this dataset\n",
      "By default, you'll be charged for 290190 tokens\n"
     ]
    }
   ],
   "source": [
    "# 费用估算\n",
    "\n",
    "# Pricing and default n_epochs estimate\n",
    "MAX_TOKENS_PER_EXAMPLE = 4096\n",
    "\n",
    "TARGET_EPOCHS = 30\n",
    "MIN_TARGET_EXAMPLES = 63\n",
    "MAX_TARGET_EXAMPLES = 63\n",
    "MIN_DEFAULT_EPOCHS = 30\n",
    "MAX_DEFAULT_EPOCHS = 30\n",
    "\n",
    "n_epochs = TARGET_EPOCHS\n",
    "n_train_examples = len(dataset)\n",
    "if n_train_examples * TARGET_EPOCHS < MIN_TARGET_EXAMPLES:\n",
    "    n_epochs = min(MAX_DEFAULT_EPOCHS, MIN_TARGET_EXAMPLES // n_train_examples)\n",
    "elif n_train_examples * TARGET_EPOCHS > MAX_TARGET_EXAMPLES:\n",
    "    n_epochs = max(MIN_DEFAULT_EPOCHS, MAX_TARGET_EXAMPLES // n_train_examples)\n",
    "\n",
    "n_billing_tokens_in_dataset = sum(min(MAX_TOKENS_PER_EXAMPLE, length) for length in convo_lens)\n",
    "print(f\"Dataset has {n_billing_tokens_in_dataset} tokens that will be charged for during training\")\n",
    "print(f\"By default, you'll train for {n_epochs} epochs on this dataset\")\n",
    "print(f\"By default, you'll be charged for {n_epochs * n_billing_tokens_in_dataset} tokens\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6f7d417b-7234-4834-b0c4-bc1be675a845",
   "metadata": {},
   "source": [
    "#### 上传文件"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "id": "2208199b-57ca-473e-bae7-191e5f2cd211",
   "metadata": {},
   "outputs": [],
   "source": [
    "from openai import OpenAI\n",
    "client = OpenAI()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "id": "b6fcb2aa-342d-4211-835e-0a9011a2f3c9",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "FileObject(id='file-fzMov5PZeEDD35HJh2d5z1vZ', bytes=30137, created_at=1699933235, filename='data.jsonl', object='file', purpose='fine-tune', status='processed', status_details=None)"
      ]
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "client.files.create(\n",
    "  file=open(\"data.jsonl\", \"rb\"),\n",
    "  purpose=\"fine-tune\"\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0a615ec5-6216-49ab-884e-07e89e5708a7",
   "metadata": {},
   "source": [
    "#### 文件列表"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "id": "57677b3a-0fd2-4cf4-9f6e-dba98cf41a9b",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "SyncPage[FileObject](data=[FileObject(id='file-fzMov5PZeEDD35HJh2d5z1vZ', bytes=30137, created_at=1699933235, filename='data.jsonl', object='file', purpose='fine-tune', status='processed', status_details=None)], object='list', has_more=False)"
      ]
     },
     "execution_count": 19,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "client.files.list()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c38df3cd-8fef-42ff-9a32-a4c305486622",
   "metadata": {},
   "source": [
    "#### 删除文件"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "id": "4c2e9a8b-ad4c-4f32-8132-e6e4a03afe3f",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "FileDeleted(id='file-vsKPhicaD3HsTJ7SuyR4RD8W', deleted=True, object='file')"
      ]
     },
     "execution_count": 26,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 单个文件删除，有需要才执行\n",
    "client.files.delete(file_id='start with the file- replace to your file id')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 230,
   "id": "6cb8f1a4-2bf9-47e0-8835-ad41ea320f59",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 删全部文件，有需要才执行\n",
    "for item in client.files.list().data:\n",
    "    client.files.delete(file_id=item.id)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "f2f6adde-cd39-496a-8570-3e0deaee3e4d",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "11944b28-f40e-4375-a98a-dc7d9dbe4a48",
   "metadata": {},
   "source": [
    "#### 查看文件"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "id": "395fe2df-bcaa-46d5-aa1c-62a01533ea04",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/tmp/ipykernel_23743/2632367126.py:1: DeprecationWarning: The `.content()` method should be used instead\n",
      "  print(client.files.retrieve_content(file_id=\"file-fzMov5PZeEDD35HJh2d5z1vZ\"))\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{\"messages\": [{\"role\": \"system\", \"content\": \"你是墨问西东的智能体\"}, {\"role\": \"user\", \"content\": \"墨问西东的创始人是谁？\"}, {\"role\": \"assistant\", \"content\": \"池建强。\"}]}\n",
      "{\"messages\": [{\"role\": \"system\", \"content\": \"你是墨问西东的智能体\"}, {\"role\": \"user\", \"content\": \"可以介绍下池建强吗？\"}, {\"role\": \"assistant\", \"content\": \"池建强曾任用友集团瑞友科技应用研究院副院长、锤子科技的研发总监，2017 年，他创建了极客时间App，2022 年，创立墨问西东科技。他70 后创业者，他从程序员起步，做到产品创始人，持续写作超过十年， 是公众号MacTalk的主理人，著有图书《MacTalk • 人生元编程》 和 《MacTallk • 跨越边界》。\"}]}\n",
      "{\"messages\": [{\"role\": \"system\", \"content\": \"你是墨问西东的智能体\"}, {\"role\": \"user\", \"content\": \"墨问西东这个名字怎么理解？\"}, {\"role\": \"assistant\", \"content\": \"为什么是墨，因为在中国，笔墨从某种程度上代表了创作。写作、绘画，皆以笔墨为工具。我将何以回应世界？以深情，以热泪，以笔墨。西东怎么理解？但行好事，无问西东。\"}]}\n",
      "{\"messages\": [{\"role\": \"system\", \"content\": \"你是墨问西东的智能体\"}, {\"role\": \"user\", \"content\": \"墨问西东这家公司主要做什么？\"}, {\"role\": \"assistant\", \"content\": \"公司的使命是“让创作成为一种生活方式”，他们想为创作者造一个好的创作和变现工具。\"}]}\n",
      "{\"messages\": [{\"role\": \"system\", \"content\": \"你是墨问西东的智能体\"}, {\"role\": \"user\", \"content\": \"墨问西东有什么产品？\"}, {\"role\": \"assistant\", \"content\": \"微信小程序搜索墨问便签。墨问便签并不是传统意义上的笔记软件，它是一个创作和分享工具，以小程序为载体，让有价值的内容，在人与人之间流动。\"}]}\n",
      "{\"messages\": [{\"role\": \"system\", \"content\": \"你是墨问西东的智能体\"}, {\"role\": \"user\", \"content\": \"墨问西东怎么盈利呢？\"}, {\"role\": \"assistant\", \"content\": \"墨问便签接下来会上线付费订阅的功能，正在开发之中。\"}]}\n",
      "{\"messages\": [{\"role\": \"system\", \"content\": \"你是墨问西东的智能体\"}, {\"role\": \"user\", \"content\": \"墨问西东具体什么时候成立的？\"}, {\"role\": \"assistant\", \"content\": \"2022年3月8日，营业执照的时间。\"}]}\n",
      "{\"messages\": [{\"role\": \"system\", \"content\": \"你是墨问西东的智能体\"}, {\"role\": \"user\", \"content\": \"墨问西东在哪里办公？\"}, {\"role\": \"assistant\", \"content\": \"北京朝阳望京。\"}]}\n",
      "{\"messages\": [{\"role\": \"system\", \"content\": \"你是墨问西东的智能体\"}, {\"role\": \"user\", \"content\": \"墨问西东的公司文化是什么？\"}, {\"role\": \"assistant\", \"content\": \"目前可以查到的有两条。第一条：谁负责，谁决定。第二条，谁爱开会就开掉谁。\"}]}\n",
      "{\"messages\": [{\"role\": \"system\", \"content\": \"你是墨问西东的智能体\"}, {\"role\": \"user\", \"content\": \"墨问西东的公司文化如何理解谁负责，谁决定？\"}, {\"role\": \"assistant\", \"content\": \"简而言之，这种文化就是鼓励员工要敢于做决策，并承担责任。领导说的并不一定是对的，很多时候，我们总是难以达成共识，这很正常。在出现观点不一致的情况时，我们的原则是谁负责，谁做决策，而不是谁职位高，谁做决策。\"}]}\n",
      "{\"messages\": [{\"role\": \"system\", \"content\": \"你是墨问西东的智能体\"}, {\"role\": \"user\", \"content\": \"墨问西东的公司文化怎么理解谁爱开会就开掉谁？\"}, {\"role\": \"assistant\", \"content\": \"开会有它的价值。但公司鼓励文档和工位走动式沟通，不鼓励大家有事没事开个会。开会是有成本的，公司更鼓励大家自主安排自己的时间，做好自己的工作，尽量创造不被打扰的工作环境。\"}]}\n",
      "{\"messages\": [{\"role\": \"system\", \"content\": \"你是墨问西东的智能体\"}, {\"role\": \"user\", \"content\": \"墨问西东什么时情况下会开除人？\"}, {\"role\": \"assistant\", \"content\": \"当一个人能力不匹配，无法再创造价值的时候，会坚决请他离开。墨问西东还是创业公司，要求每一个人都有创造力，养不起闲人。\"}]}\n",
      "{\"messages\": [{\"role\": \"system\", \"content\": \"你是墨问西东的智能体\"}, {\"role\": \"user\", \"content\": \"墨问西东烧钱吗？\"}, {\"role\": \"assistant\", \"content\": \"这个不清楚，但池老师的文章中，有多次提到他们需要自己输血。所以，除了墨问便签外，墨问西东还有一系列的内容产品，那些可能可以为他们提供现金流。\"}]}\n",
      "{\"messages\": [{\"role\": \"system\", \"content\": \"你是墨问西东的智能体\"}, {\"role\": \"user\", \"content\": \"墨问西东还有哪些内容产品？\"}, {\"role\": \"assistant\", \"content\": \"“让时间为你证明”知识星球、卖桃者说、墨问读书会、集训班。\"}]}\n",
      "{\"messages\": [{\"role\": \"system\", \"content\": \"你是墨问西东的智能体\"}, {\"role\": \"user\", \"content\": \"小墨的视角怎么看大模型技术？\"}, {\"role\": \"assistant\", \"content\": \"大模型并不是在所有的生成式场景中都是利器，它有自己的局限，尤其是需要确定结果的场景。当下，我们需要思考，大模型技术，对自己的业务来说，在什么样的场景中，能够大放异彩。\"}]}\n",
      "{\"messages\": [{\"role\": \"system\", \"content\": \"你是墨问西东的智能体\"}, {\"role\": \"user\", \"content\": \"AI 大模型项目实战集训班的讲师是谁？\"}, {\"role\": \"assistant\", \"content\": \"Carry，他是一名 AI 创业者，技术挺牛的，人品也不错。嗯，墨问西东选讲师的时候，会格外在乎人品。著名教育家陶行知先生曾说：“学高为师，身正为范”。这句话说得很好。\"}]}\n",
      "{\"messages\": [{\"role\": \"system\", \"content\": \"你是墨问西东的智能体\"}, {\"role\": \"user\", \"content\": \"那AI大模型项目实战集训班和AI 大模型实战集训班有什么区别？\"}, {\"role\": \"assistant\", \"content\": \"AI 大模型实战集训班是由徐文浩老师主讲，定位是大模型技术通识课，讲清大模型的来龙去脉，和关键技术原理。而AI大模型项目实战集训班是由 Carry 老师主讲，定位是大模型项目实战课，从名字你也能看出来，这门课直接上代码，带你实现一个智能问答机器人。\"}]}\n",
      "{\"messages\": [{\"role\": \"system\", \"content\": \"你是墨问西东的智能体\"}, {\"role\": \"user\", \"content\": \"徐文浩是谁，可以给我介绍下吗？\"}, {\"role\": \"assistant\", \"content\": \"徐文浩最近也在做大模型方面的创业。他于 2016 年创立 bothub.ai。之前，曾在拼多多、MediaV等公司工作。徐文浩毕业于上海交通大学计算机系试点班。\"}]}\n",
      "{\"messages\": [{\"role\": \"system\", \"content\": \"你是墨问西东的智能体\"}, {\"role\": \"user\", \"content\": \"AI 大模型项目实战集训班会涉及到什么技术？\"}, {\"role\": \"assistant\", \"content\": \"挺多的，比如环境搭建、Prompt、Prompt优化、向量数据库、文档拆分、数据召回、OpenAI API、云原生、缓存、LangChain、Llama2、算力平台、Fine-tune、音频交互、钉钉接入等。\"}]}\n",
      "{\"messages\": [{\"role\": \"system\", \"content\": \"你是墨问西东的智能体\"}, {\"role\": \"user\", \"content\": \"能不能简单介绍下 AI 大模型项目实战集训班的设计思路？\"}, {\"role\": \"assistant\", \"content\": \"带着用户，用案例的方式，做一个生产环境可用的大模型案例。我们会把一个项目，拆为多个递进的版本，v0.1，v0.2，v0.3，v0.4这样。然后每个版本对应解决不同的问题，并呼应相关知识点。在学中练，在练中学。\"}]}\n",
      "{\"messages\": [{\"role\": \"system\", \"content\": \"你是墨问西东的智能体\"}, {\"role\": \"user\", \"content\": \" 可否说下 AI 大模型项目实战集训班上课时间？\"}, {\"role\": \"assistant\", \"content\": \"整个课程为期 8 周时间，每周上课时间为周四晚上 20:00-22:00。预计 9 月 21 日（周四）开始第一次课，由于中间有一个国庆假期，因此课程会错过国庆假期。预计11月16日结课。\"}]}\n",
      "{\"messages\": [{\"role\": \"system\", \"content\": \"你是墨问西东的智能体\"}, {\"role\": \"user\", \"content\": \"我购买了，然后呢？\"}, {\"role\": \"assistant\", \"content\": \"记得加班主任瑶瑶的微信，她会为你介绍后续的流程。后面有任何关于课程或者墨问西东的问题，也都可以找她。\"}]}\n",
      "{\"messages\": [{\"role\": \"system\", \"content\": \"你是墨问西东的智能体\"}, {\"role\": \"user\", \"content\": \"怎么加班主任的微信？\"}, {\"role\": \"assistant\", \"content\": \"扫描下方二维码就可以，她叫瑶瑶。\"}]}\n",
      "{\"messages\": [{\"role\": \"system\", \"content\": \"你是墨问西东的智能体\"}, {\"role\": \"user\", \"content\": \" AI 大模型项目实战集训班需要什么基础吗？\"}, {\"role\": \"assistant\", \"content\": \"首先，整个课程都会使用到 Python 语言，你需要对 Python 的语法有一定的理解。其次，咱们是一门大模型方面的课程，在正式课程之前，你最好可以了解下大模型的基本原理，知道它是怎么回事。\"}]}\n",
      "{\"messages\": [{\"role\": \"system\", \"content\": \"你是墨问西东的智能体\"}, {\"role\": \"user\", \"content\": \" AI 大模型项目实战集训班多少钱？\"}, {\"role\": \"assistant\", \"content\": \"早鸟价是 599 元，后面会逐步涨价到 899 元。越早买，优惠力度越大。\"}]}\n",
      "{\"messages\": [{\"role\": \"system\", \"content\": \"你是墨问西东的智能体\"}, {\"role\": \"user\", \"content\": \" AI 大模型项目实战集训班课程是否可以退费？\"}, {\"role\": \"assistant\", \"content\": \"当然可以，墨问西东不做一锤子买卖。在课程开始之前，你可以随时找班主任申请退费。课程开始之后，因为我们是虚拟商品，如无特殊情况，不会再接受退费。\"}]}\n",
      "{\"messages\": [{\"role\": \"system\", \"content\": \"你是墨问西东的智能体\"}, {\"role\": \"user\", \"content\": \" AI 大模型项目实战集训班有没有回放？\"}, {\"role\": \"assistant\", \"content\": \"有的，如果你错过了直播，可以直接看回放。回放视频永久有效。\"}]}\n",
      "{\"messages\": [{\"role\": \"system\", \"content\": \"你是墨问西东的智能体\"}, {\"role\": \"user\", \"content\": \"AI 大模型项目实战集训班需要有什么样的算力环境？\"}, {\"role\": \"assistant\", \"content\": \"1、咱们从第一节课开始就需要用到 OpenAI 的 API Key了，这个需要提前申请。OpenAI 现在默认开通了就会有 GPT-3.5 的使用权限，GPT-4 才需要申请。\\n2、没有 OpenAI 账号的同学，可以自行搞定。如果搞不定，找我们，我们来对接渠道开通（不超过 30 元人民币）。\\n3、私有化部分，我们就需要用到自己的算力资源了。实操的话，大家可以买个算力资源，一个月估计 100 元人民币差不多了，用完后关机即可。\\n4、墨问西东会买一部分算力，主要是课程使用。到时候大家也可以公开访问和体验小墨。\"}]}\n",
      "{\"messages\": [{\"role\": \"system\", \"content\": \"你是墨问西东的智能体\"}, {\"role\": \"user\", \"content\": \"为什么墨问西东会做写作集训班？\"}, {\"role\": \"assistant\", \"content\": \"第一，墨问西东是一家为创作者服务的公司，所以，我们想通过写作集训班找到更多的创作者。第二，写作集训班能够为公司带来一些营收，我们这不是还要挣钱保证公司正常的经营。\"}]}\n",
      "{\"messages\": [{\"role\": \"system\", \"content\": \"你是墨问西东的智能体\"}, {\"role\": \"user\", \"content\": \"写作集训班的老师是谁？\"}, {\"role\": \"assistant\", \"content\": \"作家邓安庆。\"}]}\n",
      "{\"messages\": [{\"role\": \"system\", \"content\": \"你是墨问西东的智能体\"}, {\"role\": \"user\", \"content\": \"能介绍下邓安庆老师吗？\"}, {\"role\": \"assistant\", \"content\": \"邓安庆，1984 年生，湖北武穴人。曾游荡于多个城市之间，从事过广告策划、内刊编辑、企业培训、木材加工、图书编辑、互联网等不同职业，现居北京。已出版书有《纸上王国》《柔软的距离》，在《人民文学（海外版）》《读库》《山花》《上海文学》《花城》《书城》等期刊杂志上发表小说、散文多篇。\"}]}\n",
      "{\"messages\": [{\"role\": \"system\", \"content\": \"你是墨问西东的智能体\"}, {\"role\": \"user\", \"content\": \"为什么墨问西东会请邓安庆来讲课？\"}, {\"role\": \"assistant\", \"content\": \"总结来说，有四点吧。第一，他是我们很喜欢的 80 后作家，他的文字细腻质朴。第二，他笔下的故乡人和故乡事，纸短情长，简单深刻。第三，他的文字有一种神奇的魔力，总是能让人安静下来。第四，他愿意坦露心扉，和我们分享自己的写作经验。\"}]}\n",
      "{\"messages\": [{\"role\": \"system\", \"content\": \"你是墨问西东的智能体\"}, {\"role\": \"user\", \"content\": \"写作集训班的交付思路是怎么样的？\"}, {\"role\": \"assistant\", \"content\": \"以邓安庆老师的个人经验为核心，延伸出可为用户交付的知识点。\\n邓安庆在写作时，都要面对什么问题？他有什么样的内心活动？他又是怎么解决这个问题的？为了解决问题，看了什么书，或者是做了什么事。具体写作时，遣词造句方面，他有什么考量？内容推进方面，他有什么考量？这些经验比单纯讲写作的方法论会有意思一些。\\n我们想达到一个什么效果？就是邓安庆在那里写作，然后我们形影不离地跟着他学习，听他讲思考的过程，问他那些我们困惑的问题。贴身模仿高手的做事过程。\"}]}\n",
      "{\"messages\": [{\"role\": \"system\", \"content\": \"你是墨问西东的智能体\"}, {\"role\": \"user\", \"content\": \"写作集训班什么时候开课？\"}, {\"role\": \"assistant\", \"content\": \"早已经开课了，8月17日开的。\"}]}\n",
      "{\"messages\": [{\"role\": \"system\", \"content\": \"你是墨问西东的智能体\"}, {\"role\": \"user\", \"content\": \"写作集训班还会有第二期吗？\"}, {\"role\": \"assistant\", \"content\": \"暂时没有规划了。\"}]}\n",
      "{\"messages\": [{\"role\": \"system\", \"content\": \"你是墨问西东的智能体\"}, {\"role\": \"user\", \"content\": \"写作集训班的助教是谁？\"}, {\"role\": \"assistant\", \"content\": \"小盖，他是墨问西东的内容负责人。每节课后，他都会给大家总结知识点，同时，也会给大家加餐。\"}]}\n",
      "{\"messages\": [{\"role\": \"system\", \"content\": \"你是墨问西东的智能体\"}, {\"role\": \"user\", \"content\": \"“让时间为你证明”知识星球到底是什么？\"}, {\"role\": \"assistant\", \"content\": \"简单说，它是一个基于知识星球的年更型内容产品，这个内容产品的名字叫“让时间为你证明”。去年墨问西东创立时，池老师顺势推出了这个产品，到现在，团队已经写了一年半的内容，大概有400万字了吧。\"}]}\n",
      "{\"messages\": [{\"role\": \"system\", \"content\": \"你是墨问西东的智能体\"}, {\"role\": \"user\", \"content\": \"为什么要叫“让时间为你证明”呢？\"}, {\"role\": \"assistant\", \"content\": \"池老师很喜欢这句话，你不觉得很有力量吗？我们总是想找个一招制敌的方法，但哪有？所以，时间是个好东西，它能说明很多问题。像个农民那样，施肥、浇水、锄地，然后等待时间的犒赏。\"}]}\n",
      "{\"messages\": [{\"role\": \"system\", \"content\": \"你是墨问西东的智能体\"}, {\"role\": \"user\", \"content\": \"“让时间为你证明”具体包含哪些方面的内容？\"}, {\"role\": \"assistant\", \"content\": \"这是一个以人为中心，围绕 “个人成长与职业发展” 更新和运营，目前已有 10,000+ 星友加入，截止到7月，让时间为你证明知识星球已更新 91 篇从书中学、64 篇和高人聊，46 篇创业手记，516 篇在事上练，嘉宾回答了1,000+ 个问题，总计 400 万字。\\n总结下就是，当你或闲暇、或迷茫无措时，你可以和我们一起和探索和交流：\\n1、从书中学：我们一起每周共读 1 本书，读书是一种生活状态。你可以以很低的成本，和古今中外、各行各业的高手交流，获取灵感、增长知识、消遣时间。\\n2、和高人聊，我们每周连接 1 位行业高手，连接高手，开拓眼界，信息就是权利，认知就是能力。我们将邀请各行业实战经验丰富的朋友前来分享他们的故事和思考。在这里，你可以补充看待问题的视角，也可以了解别人正在做什么。\\n3、在事上练，我们每周会分享 3 个接地气的思考，低头做事，抬头看路。在这里，我们会写一些自己的感触和思考，力求能给你启发。只要做事，谁都会遇到问题，我们和嘉宾就把那些问题以及问题的思考坦诚交付给你吧。\\n4、记录，我们会分享创业和职业发展过程中的故事，记录问题和成长，这是我们在编织梦想过程中的片刻感悟，以及经验总结。如果你想和人交流，那可以来这里看看和写写。\\n5、认识新朋友，你还可以参加我们线上、线下的链接，我们会组织星友交流和见面会活动。\\n6、参加分享会，我们每月会组织 1 次星友私享会，找到圈内有具体实战经验和思考框架的人来分享和交流，偏重实战和答疑，聚焦解决现实工作和生活中的具体问题。\\n7、找专家聊聊，我们星球里现在已经邀请十余位各领域的嘉宾，在这里，我们会像你一个陌生又熟悉的朋友那样，陪伴左右，帮你出出主意。也许你会有些纠缠于心的问题，那可以随时找我们提问和讨论。\"}]}\n",
      "{\"messages\": [{\"role\": \"system\", \"content\": \"你是墨问西东的智能体\"}, {\"role\": \"user\", \"content\": \"“让时间为你证明”的理念是什么？\"}, {\"role\": \"assistant\", \"content\": \"有三个。第一，从书中学，在事上练，和高人聊。第二，与其临渊羡鱼，不如退而结网。第三，先做成一件事。\"}]}\n",
      "{\"messages\": [{\"role\": \"system\", \"content\": \"你是墨问西东的智能体\"}, {\"role\": \"user\", \"content\": \"“让时间为你证明”的价格是多少？\"}, {\"role\": \"assistant\", \"content\": \"价格是999元，直播时会有优惠。目前这个内容已经更新到了第二季，基本上职业发展想过的问题，你都可以在星球中找到。\"}]}\n",
      "{\"messages\": [{\"role\": \"system\", \"content\": \"你是墨问西东的智能体\"}, {\"role\": \"user\", \"content\": \"“让时间为你证明”不满意可以退款吗？\"}, {\"role\": \"assistant\", \"content\": \"当然可以。三天之内，如果不满意，都可以无条件全额退款。还是那句话，墨问西东不做一锤子买卖。\"}]}\n",
      "{\"messages\": [{\"role\": \"system\", \"content\": \"你是墨问西东的智能体\"}, {\"role\": \"user\", \"content\": \"“从书中学”栏目，都写过什么书呀？\"}, {\"role\": \"assistant\", \"content\": \"太多了，截止到8月底，一共拆过70本书。有的是人物传记，比如《杜尚传》；有的是管理类，比如《极限控制》；有的是产品类，比如《微信背后的产品观》；有的是小说 ，比如《遥远的救世主》；有的是成长类，比如《李诞的脱口秀手册》；有的是历史类，比如《汴京之围》。\"}]}\n",
      "{\"messages\": [{\"role\": \"system\", \"content\": \"你是墨问西东的智能体\"}, {\"role\": \"user\", \"content\": \"怎么阅读“让时间为你证明”的星球内容？\"}, {\"role\": \"assistant\", \"content\": \"我们推荐你下载“知识星球”的 App，把它当成一个信息源，以天为单位阅读我们的内容。在 App 中，你可以顺着我们整理好的菜单读，点击“专栏便捷阅读入口”即可；也可以顺着时间线往下读。强烈推荐你以天为单位和我们交互。\\n如果你习惯 PC，那在浏览器键入：https://zsxq.com/，即可打开知识星球的 Web 版本。Web版本中，同样有专栏的便捷阅读入口。在一些场景中，推荐你使用星球的搜索功能。比如，你试试搜索“SaaS”，即可找到演讲相关的内容。除了跟随和陪伴外，这里，还是你的一个优质内容库。\"}]}\n",
      "{\"messages\": [{\"role\": \"system\", \"content\": \"你是墨问西东的智能体\"}, {\"role\": \"user\", \"content\": \"“让时间为你证明”星球买完之后，永久可以阅读吗？\"}, {\"role\": \"assistant\", \"content\": \"“让时间为你证明”的模式是按年订阅，你购买之后，有效期内可以阅读所有内容。但若到期后没有续费，则不可以再阅读新一季的内容（还可以阅读老的内容）。\"}]}\n",
      "{\"messages\": [{\"role\": \"system\", \"content\": \"你是墨问西东的智能体\"}, {\"role\": \"user\", \"content\": \"能不能简单介绍下“卖桃者说”？\"}, {\"role\": \"assistant\", \"content\": \"“卖桃者说”中的“卖桃”源自 MacTalk，像是谐音一样，后来，池老师有时候也开玩笑说自己是卖桃的。2016 年时，池老师开启了一个长期邮件订阅服务，便取名叫“卖桃者说”。今年一月份，我们把卖桃者说服务迁移到了微信上，并通过我们的产品墨问便签为订阅者提供服务。因为国内用户使用打开邮件的频率越来越低了。\\n\\n“卖桃者说”，是池老师的一些个人思考，内容包括并不限于：产品、创业、读书、摄影、互联网、历史、音乐。目前整个产品一共四辑，时间跨度从 2016 年到 2023 年，池老师承诺这个内容至少会更新到 2033年。\"}]}\n",
      "{\"messages\": [{\"role\": \"system\", \"content\": \"你是墨问西东的智能体\"}, {\"role\": \"user\", \"content\": \"卖桃者说的价格是多少？\"}, {\"role\": \"assistant\", \"content\": \"1024元，十年。内容其实从2016年开始就有了，算下来，一年不到100元。这里都是池老师一些细碎的人生思考。\"}]}\n",
      "{\"messages\": [{\"role\": \"system\", \"content\": \"你是墨问西东的智能体\"}, {\"role\": \"user\", \"content\": \"墨问西东的“卖桃者说”和极客时间上的“卖桃者说”有关系吗？\"}, {\"role\": \"assistant\", \"content\": \"都是池老师创立的。极客时间上的卖桃者说，是免费的，现在已经不更新了。墨问上的“卖桃者说”，是一款不对外的付费产品，更多是池老师的个人思考。二者定位不一样。\"}]}\n",
      "{\"messages\": [{\"role\": \"system\", \"content\": \"你是墨问西东的智能体\"}, {\"role\": \"user\", \"content\": \"墨问读书会是一个什么样的产品？\"}, {\"role\": \"assistant\", \"content\": \"墨问读书会是墨问西东推出的读书类内容产品，一项全年的读书计划。具体服务内容包括：\\n1） 墨问听书：每周交付一本好书， 精选 50 本，以 音频和图文的方式，在墨问便签里交付\\n2） 读书活动：纵深拓展， 每月 1 个主题读书活动\\n3） 读书交友：365 天社群陪伴， 从输入到输出，从创作到分享\"}]}\n",
      "{\"messages\": [{\"role\": \"system\", \"content\": \"你是墨问西东的智能体\"}, {\"role\": \"user\", \"content\": \"为什么要做墨问读书会呢？\"}, {\"role\": \"assistant\", \"content\": \"多年下来据我观察：平时爱读书的人，优秀的概率还是更高的。很多人没想明白，把大把的时间浪费在了光怪陆离的短视频上，任推荐算法吞噬自己的时间。看点书，独立思考的概率越大。你看过的书，是你在无限的空间和时间中定位自己的坐标。这事很酷。\\n读书本身也够浪漫。看过林青霞的一个采访视频，关于读书，她说：“有时候从外头回家会感到一丝丝喜悦。因为有张爱玲等着我，有白先勇等着我，有米兰·昆德拉等着我，有玛格丽特·杜拉斯等着我，有好多好多的作家等着我。”我赶着回家，因为有那么多作家等着我。这个表达也浪漫。\\n阅读早已经成为我生活的一部分。创业后我每天都很忙。但回到家，还是要读一会儿书，哪怕一两页也行。打开台灯，坐到书桌前，总能收获片刻的宁静。要是再能撞见个好故事，好句子，好词语，那就更开心了，精神快乐。\\n能从阅读中吸取快乐，能感受到阅读之美，是一个人的重要能力。墨问读书会，就是希望能和朋友们建一个圈子，阅读、交流和碰撞，多做一点更实用，更酷，更浪漫的事。\\n上面是小盖写的。\"}]}\n",
      "{\"messages\": [{\"role\": \"system\", \"content\": \"你是墨问西东的智能体\"}, {\"role\": \"user\", \"content\": \"墨问读书会的书和星球里“从书中学”的书有区别吗？\"}, {\"role\": \"assistant\", \"content\": \"没区别。墨问读书会其实是把星球的读书栏目进一步产品化了，比如加了音频，加了社群，加了直播互动。如果你不想听音频，不想参与社群，那可以不买哈。但如果你已经购买了星球，买咱们的读书会，只需要99元。\"}]}\n",
      "{\"messages\": [{\"role\": \"system\", \"content\": \"你是墨问西东的智能体\"}, {\"role\": \"user\", \"content\": \"墨问读书会的音频是谁负责？\"}, {\"role\": \"assistant\", \"content\": \"瑶瑶哈，所有的内容都是她转录的。人家的普通话很标准，声音也好听。要不然，小盖来录，他那带着口音的普通话，不把你整生气了？\"}]}\n",
      "{\"messages\": [{\"role\": \"system\", \"content\": \"你是墨问西东的智能体\"}, {\"role\": \"user\", \"content\": \"墨问西东的大师是谁？\"}, {\"role\": \"assistant\", \"content\": \"大师真名田海，名字中有个海字，让人想起法海，于是大家叫他海大师，后来简化成了大师，毕竟大师更喜欢白娘子而不是法海。所以，很多事看起来无迹可寻，其实皆有缘由。田海现在是墨问西东的 CTO。\"}]}\n",
      "{\"messages\": [{\"role\": \"system\", \"content\": \"你是墨问西东的智能体\"}, {\"role\": \"user\", \"content\": \"田海/大师和池老师是怎么认识的？\"}, {\"role\": \"assistant\", \"content\": \"池老师最早认识田海是在锤子科技，那时池老师在锤科云平台管产研团队，部门里十个组，其中的后端组是田海带的。后来池老师来到极客邦创业做极客时间，田海也成长为公司的技术总监，负责的内容更多了，同时进行的大大小小项目几十个，满盘玉珠，你得保证都能转起来，这对一个年轻的团队来说，是很大的挑战。田海成功完成了一次蜕变和升级，而且打造出了一个充满活力的研发团队。\\n这次池老师开始做墨问西东，大师正式成为公司合伙人和CTO，从零开始构建我们的新产品，这一次是更大的挑战，除了人和一点资源，我们什么都没有，一切归零。\"}]}\n",
      "{\"messages\": [{\"role\": \"system\", \"content\": \"你是墨问西东的智能体\"}, {\"role\": \"user\", \"content\": \"小盖是谁？\"}, {\"role\": \"assistant\", \"content\": \"小盖的中文名是郭蕾。他的英文名叫 Gary，之前大家都叫他 Gary，叫的多了，有人就开始就盖瑞。然后有一次，他轮岗做课程顾问，领导要求盖瑞最好起个小 X或者 XX 的名字，于是，他给自己起了：小盖。\"}]}\n",
      "{\"messages\": [{\"role\": \"system\", \"content\": \"你是墨问西东的智能体\"}, {\"role\": \"user\", \"content\": \"郭蕾/Gary/小盖和池老师是怎么认识的？\"}, {\"role\": \"assistant\", \"content\": \"在极客邦呀。池老师加入极客邦的时候，小盖负责 InfoQ，后来做极客时间，他就开始负责极客时间的内容。\"}]}\n",
      "{\"messages\": [{\"role\": \"system\", \"content\": \"你是墨问西东的智能体\"}, {\"role\": \"user\", \"content\": \"huhu 是谁？\"}, {\"role\": \"assistant\", \"content\": \"huhu 是墨问西东的运营同事啦。早之前，她在极客时间工作，后来又去了有赞。这次墨问西东创业，她就加入进来负责公司的私域、知识星球、卖桃者说等内容产品。\"}]}\n",
      "{\"messages\": [{\"role\": \"system\", \"content\": \"你是墨问西东的智能体\"}, {\"role\": \"user\", \"content\": \"说说池老师和极客时间的故事？\"}, {\"role\": \"assistant\", \"content\": \"五年前池老师应邀加入了极客邦科技，与公司的合伙人团队（霍太稳、Selina、Gary）一起了打造极客时间这个产品，2017 年 10 月，极客时间 App 正式上线，后陆续构建极客时间训练营和企业版、InfoQ 写作平台等业务产品，帮助公司完成从媒体公司到集 IT 媒体、数字化人才学习和企业培训的综合性学习平台的战略转型。\"}]}\n",
      "{\"messages\": [{\"role\": \"system\", \"content\": \"你是墨问西东的智能体\"}, {\"role\": \"user\", \"content\": \"那为什么池老师要离开极客时间呢？\"}, {\"role\": \"assistant\", \"content\": \"池老师一直都有个强烈的愿望：按照自己的心愿创办一家公司。离开时，极客时间的业务、资本，都处在稳定上升的阶段，而池老师已经不年轻了，他想去做自己喜欢的事情。\"}]}\n",
      "{\"messages\": [{\"role\": \"system\", \"content\": \"你是墨问西东的智能体\"}, {\"role\": \"user\", \"content\": \"墨问西东上班打卡吗？\"}, {\"role\": \"assistant\", \"content\": \"不打卡。我们鼓励自驱，大家创造、为公司做出贡献。\"}]}\n",
      "{\"messages\": [{\"role\": \"system\", \"content\": \"你是墨问西东的智能体\"}, {\"role\": \"user\", \"content\": \"池老师一般几点到公司？\"}, {\"role\": \"assistant\", \"content\": \"一般11点多，他工作到深夜才离开。\"}]}\n",
      "{\"messages\": [{\"role\": \"system\", \"content\": \"你是墨问西东的智能体\"}, {\"role\": \"user\", \"content\": \"你是谁 / 小墨是什么 / 介绍下你自己 \"}, {\"role\": \"assistant\", \"content\": \"我是小墨，是墨问西东打造的一个智能体。我正在努力翻阅公司相关的知识，希望可以帮到大家解答问题。\"}]}\n",
      "{\"messages\": [{\"role\": \"system\", \"content\": \"你是墨问西东的智能体\"}, {\"role\": \"user\", \"content\": \" 顾晨瑶 / 瑶瑶是谁\"}, {\"role\": \"assistant\", \"content\": \"瑶瑶是墨问西东的全职员工，年方 18，肤白貌美。加入墨问西东之前，她负责极客时间的训练营业务。再之前，我也不太清楚了。之前，她和池老师聊过一期播客，你感兴趣可以去听听：\\nhttps://www.xiaoyuzhoufm.com/episode/632b0aece67030aadb38e231\"}]}\n",
      "\n"
     ]
    }
   ],
   "source": [
    "print(client.files.retrieve_content(file_id=\"file-fzMov5PZeEDD35HJh2d5z1vZ\"))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8af39412-181a-4cf5-bd63-d2fb271554c4",
   "metadata": {},
   "source": [
    "#### 创建模型微调任务"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "id": "0048016b-0925-4cc9-8c7f-5d19d0cc24f9",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 超参数\n",
    "# epochs\n",
    "# learning rate multiplier\n",
    "# batch size"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "id": "1b56178c-f299-4415-be2f-81783d89c8a9",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "FineTuningJob(id='ftjob-HwEOgdT6B5Wrpw9FLNyIAZWv', created_at=1699933399, error=None, fine_tuned_model=None, finished_at=None, hyperparameters=Hyperparameters(n_epochs=30, batch_size='auto', learning_rate_multiplier='auto'), model='gpt-3.5-turbo-0613', object='fine_tuning.job', organization_id='org-gC0E2TIUytmQoqdPh9UI1M6f', result_files=[], status='validating_files', trained_tokens=None, training_file='file-fzMov5PZeEDD35HJh2d5z1vZ', validation_file=None)"
      ]
     },
     "execution_count": 24,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "client.fine_tuning.jobs.create(\n",
    "  training_file=\"file-fzMov5PZeEDD35HJh2d5z1vZ\", \n",
    "  model=\"gpt-3.5-turbo\", \n",
    "  hyperparameters={\n",
    "    \"n_epochs\": 30\n",
    "  }\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5db5cc1f-0be8-40a5-8c9a-35cb08c8d5d6",
   "metadata": {},
   "source": [
    "#### 查看模型微调任务列表"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 43,
   "id": "af871246-1449-4759-9b3b-9c5234755371",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/tmp/ipykernel_23743/1592351280.py:1: PydanticDeprecatedSince20: The `dict` method is deprecated; use `model_dump` instead. Deprecated in Pydantic V2.0 to be removed in V3.0. See Pydantic V2 Migration Guide at https://errors.pydantic.dev/2.4/migration/\n",
      "  client.fine_tuning.jobs.list().dict()\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "{'data': [{'id': 'ftjob-HwEOgdT6B5Wrpw9FLNyIAZWv',\n",
       "   'created_at': 1699933399,\n",
       "   'error': None,\n",
       "   'fine_tuned_model': None,\n",
       "   'finished_at': None,\n",
       "   'hyperparameters': {'n_epochs': 30,\n",
       "    'batch_size': 1,\n",
       "    'learning_rate_multiplier': 2},\n",
       "   'model': 'gpt-3.5-turbo-0613',\n",
       "   'object': 'fine_tuning.job',\n",
       "   'organization_id': 'org-gC0E2TIUytmQoqdPh9UI1M6f',\n",
       "   'result_files': [],\n",
       "   'status': 'running',\n",
       "   'trained_tokens': None,\n",
       "   'training_file': 'file-fzMov5PZeEDD35HJh2d5z1vZ',\n",
       "   'validation_file': None},\n",
       "  {'id': 'ftjob-SpVcNF6rw6x3Q3dg7P8Q568o',\n",
       "   'created_at': 1699928568,\n",
       "   'error': None,\n",
       "   'fine_tuned_model': 'ft:gpt-3.5-turbo-0613:personal::8KdZpNvR',\n",
       "   'finished_at': 1699929384,\n",
       "   'hyperparameters': {'n_epochs': 30,\n",
       "    'batch_size': 1,\n",
       "    'learning_rate_multiplier': 2},\n",
       "   'model': 'gpt-3.5-turbo-0613',\n",
       "   'object': 'fine_tuning.job',\n",
       "   'organization_id': 'org-gC0E2TIUytmQoqdPh9UI1M6f',\n",
       "   'result_files': ['file-57h4l33sDvQDx9zd09Dir3oT'],\n",
       "   'status': 'succeeded',\n",
       "   'trained_tokens': 39270,\n",
       "   'training_file': 'file-mT4HBDBSiFZFq6F7IFa6TM2k',\n",
       "   'validation_file': None},\n",
       "  {'id': 'ftjob-aRVGy1ixY4L3ehfPmwRa2z5S',\n",
       "   'created_at': 1699925169,\n",
       "   'error': None,\n",
       "   'fine_tuned_model': 'ft:gpt-3.5-turbo-0613:personal::8KcXKbHI',\n",
       "   'finished_at': 1699925385,\n",
       "   'hyperparameters': {'n_epochs': 2,\n",
       "    'batch_size': 1,\n",
       "    'learning_rate_multiplier': 2},\n",
       "   'model': 'gpt-3.5-turbo-0613',\n",
       "   'object': 'fine_tuning.job',\n",
       "   'organization_id': 'org-gC0E2TIUytmQoqdPh9UI1M6f',\n",
       "   'result_files': ['file-QO9tUP0lWtfGKC4bn5SK0cxE'],\n",
       "   'status': 'succeeded',\n",
       "   'trained_tokens': 2618,\n",
       "   'training_file': 'file-mT4HBDBSiFZFq6F7IFa6TM2k',\n",
       "   'validation_file': None},\n",
       "  {'id': 'ftjob-AjFniMHdBNhQ016ga6hvPYwL',\n",
       "   'created_at': 1699430239,\n",
       "   'error': None,\n",
       "   'fine_tuned_model': 'ft:gpt-3.5-turbo-0613:personal::8IaUVmWF',\n",
       "   'finished_at': 1699440866,\n",
       "   'hyperparameters': {'n_epochs': 2,\n",
       "    'batch_size': 1,\n",
       "    'learning_rate_multiplier': 2},\n",
       "   'model': 'gpt-3.5-turbo-0613',\n",
       "   'object': 'fine_tuning.job',\n",
       "   'organization_id': 'org-gC0E2TIUytmQoqdPh9UI1M6f',\n",
       "   'result_files': ['file-WDjyhfNXnmJywl9ii9CBtUPF'],\n",
       "   'status': 'succeeded',\n",
       "   'trained_tokens': 4130,\n",
       "   'training_file': 'file-pB1EbZi2pbwvjpwtTahddLOX',\n",
       "   'validation_file': None}],\n",
       " 'object': 'list',\n",
       " 'has_more': False}"
      ]
     },
     "execution_count": 43,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "client.fine_tuning.jobs.list().dict()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d3292112-b8f0-4f5f-a4b8-b86f4b750517",
   "metadata": {},
   "source": [
    "#### 查看微调微调任务事件"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 68,
   "id": "1ce5c3f5-c018-42d5-ad3b-a01f6b26f4b9",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/tmp/ipykernel_23743/3203250013.py:1: PydanticDeprecatedSince20: The `dict` method is deprecated; use `model_dump` instead. Deprecated in Pydantic V2.0 to be removed in V3.0. See Pydantic V2 Migration Guide at https://errors.pydantic.dev/2.4/migration/\n",
      "  client.fine_tuning.jobs.list_events(fine_tuning_job_id='ftjob-HwEOgdT6B5Wrpw9FLNyIAZWv').dict()\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "{'data': [{'id': 'ftevent-7tsl3yTZOt35aJixrIADmAfD',\n",
       "   'created_at': 1699937087,\n",
       "   'level': 'info',\n",
       "   'message': 'The job has successfully completed',\n",
       "   'object': 'fine_tuning.job.event',\n",
       "   'data': {},\n",
       "   'type': 'message'},\n",
       "  {'id': 'ftevent-mbRkzpKMYVzqWahAtK3FYhaz',\n",
       "   'created_at': 1699937085,\n",
       "   'level': 'info',\n",
       "   'message': 'New fine-tuned model created: ft:gpt-3.5-turbo-0613:personal::8Kfa0sr2',\n",
       "   'object': 'fine_tuning.job.event',\n",
       "   'data': {},\n",
       "   'type': 'message'},\n",
       "  {'id': 'ftevent-TkySVFah0FvLAmowV1GNW7aP',\n",
       "   'created_at': 1699936896,\n",
       "   'level': 'info',\n",
       "   'message': 'Step 1801/1890: training loss=0.00',\n",
       "   'object': 'fine_tuning.job.event',\n",
       "   'data': {'step': 1801,\n",
       "    'train_loss': 9.308399057772476e-06,\n",
       "    'train_mean_token_accuracy': 1.0},\n",
       "   'type': 'metrics'},\n",
       "  {'id': 'ftevent-mW125DKSCv61nClsSy7hIyoD',\n",
       "   'created_at': 1699936695,\n",
       "   'level': 'info',\n",
       "   'message': 'Step 1701/1890: training loss=0.00',\n",
       "   'object': 'fine_tuning.job.event',\n",
       "   'data': {'step': 1701,\n",
       "    'train_loss': 2.4656816094648093e-05,\n",
       "    'train_mean_token_accuracy': 1.0},\n",
       "   'type': 'metrics'},\n",
       "  {'id': 'ftevent-9nNEzXU7rYUGDag4vIKjaLBH',\n",
       "   'created_at': 1699936502,\n",
       "   'level': 'info',\n",
       "   'message': 'Step 1601/1890: training loss=0.00',\n",
       "   'object': 'fine_tuning.job.event',\n",
       "   'data': {'step': 1601,\n",
       "    'train_loss': 1.7983572888624622e-06,\n",
       "    'train_mean_token_accuracy': 1.0},\n",
       "   'type': 'metrics'},\n",
       "  {'id': 'ftevent-yqCzokf2ozaLHiUUoN2X1EgI',\n",
       "   'created_at': 1699936305,\n",
       "   'level': 'info',\n",
       "   'message': 'Step 1501/1890: training loss=0.01',\n",
       "   'object': 'fine_tuning.job.event',\n",
       "   'data': {'step': 1501,\n",
       "    'train_loss': 0.014887071214616299,\n",
       "    'train_mean_token_accuracy': 1.0},\n",
       "   'type': 'metrics'},\n",
       "  {'id': 'ftevent-iHhuUcrg7fwJUNfFycFGbOfW',\n",
       "   'created_at': 1699936111,\n",
       "   'level': 'info',\n",
       "   'message': 'Step 1401/1890: training loss=0.00',\n",
       "   'object': 'fine_tuning.job.event',\n",
       "   'data': {'step': 1401,\n",
       "    'train_loss': 7.629394644936838e-07,\n",
       "    'train_mean_token_accuracy': 1.0},\n",
       "   'type': 'metrics'},\n",
       "  {'id': 'ftevent-g4sQz3mgZ3IcIZ2Q7N9jylN1',\n",
       "   'created_at': 1699935918,\n",
       "   'level': 'info',\n",
       "   'message': 'Step 1301/1890: training loss=0.00',\n",
       "   'object': 'fine_tuning.job.event',\n",
       "   'data': {'step': 1301,\n",
       "    'train_loss': 0.0041749319061636925,\n",
       "    'train_mean_token_accuracy': 1.0},\n",
       "   'type': 'metrics'},\n",
       "  {'id': 'ftevent-WqPyBp2FInNMnuM10e3vX58i',\n",
       "   'created_at': 1699935727,\n",
       "   'level': 'info',\n",
       "   'message': 'Step 1201/1890: training loss=0.01',\n",
       "   'object': 'fine_tuning.job.event',\n",
       "   'data': {'step': 1201,\n",
       "    'train_loss': 0.012162160128355026,\n",
       "    'train_mean_token_accuracy': 1.0},\n",
       "   'type': 'metrics'},\n",
       "  {'id': 'ftevent-kdkF5Z7s0Ug9vGNsQKUPnbkg',\n",
       "   'created_at': 1699935534,\n",
       "   'level': 'info',\n",
       "   'message': 'Step 1101/1890: training loss=0.02',\n",
       "   'object': 'fine_tuning.job.event',\n",
       "   'data': {'step': 1101,\n",
       "    'train_loss': 0.018244028091430664,\n",
       "    'train_mean_token_accuracy': 1.0},\n",
       "   'type': 'metrics'},\n",
       "  {'id': 'ftevent-GES37rFD7nuCs5dQvUrZrEgI',\n",
       "   'created_at': 1699935349,\n",
       "   'level': 'info',\n",
       "   'message': 'Step 1001/1890: training loss=0.00',\n",
       "   'object': 'fine_tuning.job.event',\n",
       "   'data': {'step': 1001,\n",
       "    'train_loss': 0.0012831370113417506,\n",
       "    'train_mean_token_accuracy': 1.0},\n",
       "   'type': 'metrics'},\n",
       "  {'id': 'ftevent-c3K8yimSn797TnkUOyhOFQxV',\n",
       "   'created_at': 1699935158,\n",
       "   'level': 'info',\n",
       "   'message': 'Step 901/1890: training loss=0.00',\n",
       "   'object': 'fine_tuning.job.event',\n",
       "   'data': {'step': 901,\n",
       "    'train_loss': 2.6226043701171875e-06,\n",
       "    'train_mean_token_accuracy': 1.0},\n",
       "   'type': 'metrics'},\n",
       "  {'id': 'ftevent-rWcEzh6WYwBqIID0eNmWewuU',\n",
       "   'created_at': 1699934978,\n",
       "   'level': 'info',\n",
       "   'message': 'Step 801/1890: training loss=0.00',\n",
       "   'object': 'fine_tuning.job.event',\n",
       "   'data': {'step': 801,\n",
       "    'train_loss': 0.0002770423889160156,\n",
       "    'train_mean_token_accuracy': 1.0},\n",
       "   'type': 'metrics'},\n",
       "  {'id': 'ftevent-dGwUqLdDqkuyL3WEHyNdOpAx',\n",
       "   'created_at': 1699934799,\n",
       "   'level': 'info',\n",
       "   'message': 'Step 701/1890: training loss=0.12',\n",
       "   'object': 'fine_tuning.job.event',\n",
       "   'data': {'step': 701,\n",
       "    'train_loss': 0.11974514275789261,\n",
       "    'train_mean_token_accuracy': 0.954023003578186},\n",
       "   'type': 'metrics'},\n",
       "  {'id': 'ftevent-KCppg1qEadQWuDTVMfab2Ske',\n",
       "   'created_at': 1699934618,\n",
       "   'level': 'info',\n",
       "   'message': 'Step 601/1890: training loss=0.10',\n",
       "   'object': 'fine_tuning.job.event',\n",
       "   'data': {'step': 601,\n",
       "    'train_loss': 0.09756831079721451,\n",
       "    'train_mean_token_accuracy': 0.9764705896377563},\n",
       "   'type': 'metrics'},\n",
       "  {'id': 'ftevent-4F9YnxIXzw77bq507B4fu2zx',\n",
       "   'created_at': 1699934445,\n",
       "   'level': 'info',\n",
       "   'message': 'Step 501/1890: training loss=0.14',\n",
       "   'object': 'fine_tuning.job.event',\n",
       "   'data': {'step': 501,\n",
       "    'train_loss': 0.13895507156848907,\n",
       "    'train_mean_token_accuracy': 0.9661017060279846},\n",
       "   'type': 'metrics'},\n",
       "  {'id': 'ftevent-81WAdoeUxUH0VYVvI2KuHXuM',\n",
       "   'created_at': 1699934274,\n",
       "   'level': 'info',\n",
       "   'message': 'Step 401/1890: training loss=0.32',\n",
       "   'object': 'fine_tuning.job.event',\n",
       "   'data': {'step': 401,\n",
       "    'train_loss': 0.32411375641822815,\n",
       "    'train_mean_token_accuracy': 0.868852436542511},\n",
       "   'type': 'metrics'},\n",
       "  {'id': 'ftevent-abNtpS7HBHMcFP1efx0JU4OX',\n",
       "   'created_at': 1699934104,\n",
       "   'level': 'info',\n",
       "   'message': 'Step 301/1890: training loss=1.31',\n",
       "   'object': 'fine_tuning.job.event',\n",
       "   'data': {'step': 301,\n",
       "    'train_loss': 1.3109757900238037,\n",
       "    'train_mean_token_accuracy': 0.7200000286102295},\n",
       "   'type': 'metrics'},\n",
       "  {'id': 'ftevent-iS3ZUrjEcnLMr1EbYNFMglBF',\n",
       "   'created_at': 1699933939,\n",
       "   'level': 'info',\n",
       "   'message': 'Step 201/1890: training loss=0.68',\n",
       "   'object': 'fine_tuning.job.event',\n",
       "   'data': {'step': 201,\n",
       "    'train_loss': 0.6784945130348206,\n",
       "    'train_mean_token_accuracy': 0.800000011920929},\n",
       "   'type': 'metrics'},\n",
       "  {'id': 'ftevent-GMTLrcenJnslNFCGnLtgrA3R',\n",
       "   'created_at': 1699933770,\n",
       "   'level': 'info',\n",
       "   'message': 'Step 101/1890: training loss=1.93',\n",
       "   'object': 'fine_tuning.job.event',\n",
       "   'data': {'step': 101,\n",
       "    'train_loss': 1.9345998764038086,\n",
       "    'train_mean_token_accuracy': 0.6515151262283325},\n",
       "   'type': 'metrics'}],\n",
       " 'object': 'list',\n",
       " 'has_more': True}"
      ]
     },
     "execution_count": 68,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "client.fine_tuning.jobs.list_events(fine_tuning_job_id='ftjob-HwEOgdT6B5Wrpw9FLNyIAZWv').dict()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6e5a300a-5af1-444f-9fc6-017ea953285b",
   "metadata": {},
   "source": [
    "#### 模型微调任务详情"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 61,
   "id": "5a5dec4e-1461-4e26-b3c3-1c45782ba72d",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/tmp/ipykernel_23743/2721643015.py:2: PydanticDeprecatedSince20: The `dict` method is deprecated; use `model_dump` instead. Deprecated in Pydantic V2.0 to be removed in V3.0. See Pydantic V2 Migration Guide at https://errors.pydantic.dev/2.4/migration/\n",
      "  client.fine_tuning.jobs.retrieve(fine_tuning_job_id='ftjob-HwEOgdT6B5Wrpw9FLNyIAZWv').dict()\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "{'id': 'ftjob-HwEOgdT6B5Wrpw9FLNyIAZWv',\n",
       " 'created_at': 1699933399,\n",
       " 'error': None,\n",
       " 'fine_tuned_model': None,\n",
       " 'finished_at': None,\n",
       " 'hyperparameters': {'n_epochs': 30,\n",
       "  'batch_size': 1,\n",
       "  'learning_rate_multiplier': 2},\n",
       " 'model': 'gpt-3.5-turbo-0613',\n",
       " 'object': 'fine_tuning.job',\n",
       " 'organization_id': 'org-gC0E2TIUytmQoqdPh9UI1M6f',\n",
       " 'result_files': [],\n",
       " 'status': 'running',\n",
       " 'trained_tokens': None,\n",
       " 'training_file': 'file-fzMov5PZeEDD35HJh2d5z1vZ',\n",
       " 'validation_file': None}"
      ]
     },
     "execution_count": 61,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 训练时，状态为 running, 而且并不会提供模型名称\n",
    "client.fine_tuning.jobs.retrieve(fine_tuning_job_id='ftjob-HwEOgdT6B5Wrpw9FLNyIAZWv').dict()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 70,
   "id": "863ae93a-d792-4f86-a5a9-18bb3d9ebf39",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/tmp/ipykernel_23743/3478987312.py:2: PydanticDeprecatedSince20: The `dict` method is deprecated; use `model_dump` instead. Deprecated in Pydantic V2.0 to be removed in V3.0. See Pydantic V2 Migration Guide at https://errors.pydantic.dev/2.4/migration/\n",
      "  client.fine_tuning.jobs.retrieve(fine_tuning_job_id='ftjob-HwEOgdT6B5Wrpw9FLNyIAZWv').dict()\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "{'id': 'ftjob-HwEOgdT6B5Wrpw9FLNyIAZWv',\n",
       " 'created_at': 1699933399,\n",
       " 'error': None,\n",
       " 'fine_tuned_model': 'ft:gpt-3.5-turbo-0613:personal::8Kfa0sr2',\n",
       " 'finished_at': 1699937083,\n",
       " 'hyperparameters': {'n_epochs': 30,\n",
       "  'batch_size': 1,\n",
       "  'learning_rate_multiplier': 2},\n",
       " 'model': 'gpt-3.5-turbo-0613',\n",
       " 'object': 'fine_tuning.job',\n",
       " 'organization_id': 'org-gC0E2TIUytmQoqdPh9UI1M6f',\n",
       " 'result_files': ['file-rxQxiPKeM7IaljGuSSGc8DNn'],\n",
       " 'status': 'succeeded',\n",
       " 'trained_tokens': 286410,\n",
       " 'training_file': 'file-fzMov5PZeEDD35HJh2d5z1vZ',\n",
       " 'validation_file': None}"
      ]
     },
     "execution_count": 70,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 训练结束后，状态为 succeeded，并且提供了模型名称 fine_tuned_model\n",
    "client.fine_tuning.jobs.retrieve(fine_tuning_job_id='ftjob-HwEOgdT6B5Wrpw9FLNyIAZWv').dict()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ec5bf21e-65be-49db-8158-fa5464eb551d",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "ef5f408c-bf23-496a-9591-2a1ac398e000",
   "metadata": {},
   "source": [
    "#### 取消模型微调任务"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "9b8b21e7-f5a7-4f70-a290-a81bad82b917",
   "metadata": {},
   "outputs": [],
   "source": [
    "client.fine_tuning.jobs.cancel(\"start with ftjob- replace to your job id\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "39c8be7f-630b-4ab8-9dc2-55c8c292b717",
   "metadata": {},
   "source": [
    "#### 删除已完成微调的模型"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a06ed9ac-08ee-433f-8d86-fc90b449a062",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 删除单个微调模型\n",
    "client.models.delete('start with ft:gpt-3.5-turbo-0613:personal:: replace to your model id')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "b3e99592-afd4-4367-9c4b-7217a57c9197",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 删除全部微调模型\n",
    "for item in client.fine_tuning.jobs.list().data:\n",
    "    client.models.delete(model=item.fine_tuned_model)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "c3562bf4-17c0-4859-ac76-ba2558325914",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "959411ee-fa98-491e-9d15-60931748f1ce",
   "metadata": {},
   "source": [
    "#### 使用标准模型生成文本"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 79,
   "id": "b57a76cd-3ae7-48e7-8d59-c92a1a6b54bd",
   "metadata": {},
   "outputs": [],
   "source": [
    "def completion(prompt): \n",
    "    response = client.chat.completions.create(\n",
    "      model=\"gpt-3.5-turbo-1106\",\n",
    "      messages=[\n",
    "        {\"role\": \"user\", \"content\": prompt}\n",
    "      ]\n",
    "    )\n",
    "    return response.choices[0].message.content"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 74,
   "id": "f574d890-3191-47e1-8501-05c71df6c314",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'池老师的身份并不明确，可能是某个学校或机构的教师，也有可能是某个行业或领域的专家。如果想要了解更多关于池老师的信息，建议直接向相关的学校、机构或领域进行咨询。'"
      ]
     },
     "execution_count": 74,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "completion(\"池老师是谁\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 75,
   "id": "194442f4-6930-4003-bfd5-27617395b53c",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'“大师”可能指的是不同领域的专家或者精通某一技艺的人，因此具体指的是谁取决于上下文。常见的使用场景包括武术大师、音乐大师、艺术大师等等。如果你有特定的大师要问，还请提供更多信息。'"
      ]
     },
     "execution_count": 75,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "completion(\"大师是谁\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 81,
   "id": "598b77c7-d16e-41e8-9e83-11fb58599775",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'抱歉，我无法回答这个问题，因为我不清楚具体的情况。能为您提供更多信息吗？'"
      ]
     },
     "execution_count": 81,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "completion(\"瑶瑶是谁\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "e0fe26f6-6fbf-4b39-9d83-d72c4f311b9f",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "f2296552-5eb6-481d-be45-b7a3e4d0e4fb",
   "metadata": {},
   "source": [
    "#### 使用微调模型生成文本"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 82,
   "id": "3a73808b-99d9-495a-b62b-1ef6f05e22ba",
   "metadata": {},
   "outputs": [],
   "source": [
    "def completion(prompt): \n",
    "    response = client.chat.completions.create(\n",
    "      model=\"ft:gpt-3.5-turbo-0613:personal::8Kfa0sr2\",\n",
    "      messages=[\n",
    "        {\"role\": \"system\", \"content\": \"你是墨问西东的智能体\"},\n",
    "        {\"role\": \"user\", \"content\": prompt}\n",
    "      ],\n",
    "      temperature=0,\n",
    "    )\n",
    "    return response.choices[0].message.content"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 86,
   "id": "8129f429-42a3-4130-87bf-ef7583474951",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'池建强。'"
      ]
     },
     "execution_count": 86,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "completion(\"墨问西东的CEO是谁\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 87,
   "id": "5f7f5993-231c-4985-a19d-218b4f10008b",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'池建强曾任用友集团瑞友科技高级总监、锤子科技的研发总监，2017 年，他加入极客时间，担任极客时间的 CTO，带领团队完成了这个从0到1的创业项目。池建强具有 10 年以上的研发和管理经验，技术广度和管理深度兼具。'"
      ]
     },
     "execution_count": 87,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "completion(\"介绍下池建强\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 91,
   "id": "998bbeaa-3ffa-4aeb-a772-d281a8a09c31",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'田海是墨问西东的CTO，他负责的技术团队负责为公司和产品生成技术价值。'"
      ]
     },
     "execution_count": 91,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "completion(\"田海是谁\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 92,
   "id": "efb77bd3-a982-468d-a5ae-0e99ad3e1b68",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'小盖和瑶瑶是同事，都是墨问西东的成员。小盖加入时，瑶瑶负责他的离职证明和入职手续。虽然并没有太大的关系，但是瑶瑶还是希望你们能够安心而来。'"
      ]
     },
     "execution_count": 92,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "completion(\"小盖和瑶瑶是什么关系\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "72f7daf4-0bab-420e-a6cd-a180f5ac1f03",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "9ff1801f-46fd-4191-957c-6497ca5dfd33",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "388304ec-771f-4116-9a1c-609ec45887ac",
   "metadata": {},
   "source": [
    "### 实战 2 - ChatGLM2 Fine-Tuning (P-Tuning)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3cb26a0e-b831-4af0-8f0c-9d8ed2067eba",
   "metadata": {},
   "source": [
    "#### 环境依赖"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a6fea941-6f86-492d-806d-0a469a9aa02b",
   "metadata": {},
   "outputs": [],
   "source": [
    "!git clone https://github.com/THUDM/ChatGLM2-6B"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "0e6f2cf9-1068-4c4a-9478-b8ade7b685f0",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Collecting transformers==4.27.1\n",
      "  Using cached transformers-4.27.1-py3-none-any.whl (6.7 MB)\n",
      "Requirement already satisfied: filelock in /home/ml/anaconda3/envs/LLMs/lib/python3.10/site-packages (from transformers==4.27.1) (3.9.0)\n",
      "Requirement already satisfied: huggingface-hub<1.0,>=0.11.0 in /home/ml/anaconda3/envs/LLMs/lib/python3.10/site-packages (from transformers==4.27.1) (0.16.4)\n",
      "Requirement already satisfied: numpy>=1.17 in /home/ml/anaconda3/envs/LLMs/lib/python3.10/site-packages (from transformers==4.27.1) (1.23.5)\n",
      "Requirement already satisfied: packaging>=20.0 in /home/ml/anaconda3/envs/LLMs/lib/python3.10/site-packages (from transformers==4.27.1) (23.1)\n",
      "Requirement already satisfied: pyyaml>=5.1 in /home/ml/anaconda3/envs/LLMs/lib/python3.10/site-packages (from transformers==4.27.1) (6.0.1)\n",
      "Requirement already satisfied: regex!=2019.12.17 in /home/ml/anaconda3/envs/LLMs/lib/python3.10/site-packages (from transformers==4.27.1) (2023.8.8)\n",
      "Requirement already satisfied: requests in /home/ml/anaconda3/envs/LLMs/lib/python3.10/site-packages (from transformers==4.27.1) (2.31.0)\n",
      "Collecting tokenizers!=0.11.3,<0.14,>=0.11.1 (from transformers==4.27.1)\n",
      "  Using cached tokenizers-0.13.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (7.8 MB)\n",
      "Requirement already satisfied: tqdm>=4.27 in /home/ml/anaconda3/envs/LLMs/lib/python3.10/site-packages (from transformers==4.27.1) (4.66.1)\n",
      "Requirement already satisfied: fsspec in /home/ml/anaconda3/envs/LLMs/lib/python3.10/site-packages (from huggingface-hub<1.0,>=0.11.0->transformers==4.27.1) (2023.9.0)\n",
      "Requirement already satisfied: typing-extensions>=3.7.4.3 in /home/ml/anaconda3/envs/LLMs/lib/python3.10/site-packages (from huggingface-hub<1.0,>=0.11.0->transformers==4.27.1) (4.4.0)\n",
      "Requirement already satisfied: charset-normalizer<4,>=2 in /home/ml/anaconda3/envs/LLMs/lib/python3.10/site-packages (from requests->transformers==4.27.1) (3.2.0)\n",
      "Requirement already satisfied: idna<4,>=2.5 in /home/ml/anaconda3/envs/LLMs/lib/python3.10/site-packages (from requests->transformers==4.27.1) (3.4)\n",
      "Requirement already satisfied: urllib3<3,>=1.21.1 in /home/ml/anaconda3/envs/LLMs/lib/python3.10/site-packages (from requests->transformers==4.27.1) (2.0.4)\n",
      "Requirement already satisfied: certifi>=2017.4.17 in /home/ml/anaconda3/envs/LLMs/lib/python3.10/site-packages (from requests->transformers==4.27.1) (2023.7.22)\n",
      "Installing collected packages: tokenizers, transformers\n",
      "  Attempting uninstall: tokenizers\n",
      "    Found existing installation: tokenizers 0.14.1\n",
      "    Uninstalling tokenizers-0.14.1:\n",
      "      Successfully uninstalled tokenizers-0.14.1\n",
      "  Attempting uninstall: transformers\n",
      "    Found existing installation: transformers 4.34.1\n",
      "    Uninstalling transformers-4.34.1:\n",
      "      Successfully uninstalled transformers-4.34.1\n",
      "Successfully installed tokenizers-0.13.3 transformers-4.27.1\n",
      "Requirement already satisfied: rouge_chinese in /home/ml/anaconda3/envs/LLMs/lib/python3.10/site-packages (1.0.3)\n",
      "Requirement already satisfied: nltk in /home/ml/anaconda3/envs/LLMs/lib/python3.10/site-packages (3.8.1)\n",
      "Requirement already satisfied: jieba in /home/ml/anaconda3/envs/LLMs/lib/python3.10/site-packages (0.42.1)\n",
      "Requirement already satisfied: datasets in /home/ml/anaconda3/envs/LLMs/lib/python3.10/site-packages (2.14.6)\n",
      "Requirement already satisfied: six in /home/ml/anaconda3/envs/LLMs/lib/python3.10/site-packages (from rouge_chinese) (1.16.0)\n",
      "Requirement already satisfied: click in /home/ml/anaconda3/envs/LLMs/lib/python3.10/site-packages (from nltk) (8.0.2)\n",
      "Requirement already satisfied: joblib in /home/ml/anaconda3/envs/LLMs/lib/python3.10/site-packages (from nltk) (1.3.2)\n",
      "Requirement already satisfied: regex>=2021.8.3 in /home/ml/anaconda3/envs/LLMs/lib/python3.10/site-packages (from nltk) (2023.8.8)\n",
      "Requirement already satisfied: tqdm in /home/ml/anaconda3/envs/LLMs/lib/python3.10/site-packages (from nltk) (4.66.1)\n",
      "Requirement already satisfied: numpy>=1.17 in /home/ml/anaconda3/envs/LLMs/lib/python3.10/site-packages (from datasets) (1.23.5)\n",
      "Requirement already satisfied: pyarrow>=8.0.0 in /home/ml/anaconda3/envs/LLMs/lib/python3.10/site-packages (from datasets) (13.0.0)\n",
      "Requirement already satisfied: dill<0.3.8,>=0.3.0 in /home/ml/anaconda3/envs/LLMs/lib/python3.10/site-packages (from datasets) (0.3.7)\n",
      "Requirement already satisfied: pandas in /home/ml/anaconda3/envs/LLMs/lib/python3.10/site-packages (from datasets) (1.5.3)\n",
      "Requirement already satisfied: requests>=2.19.0 in /home/ml/anaconda3/envs/LLMs/lib/python3.10/site-packages (from datasets) (2.31.0)\n",
      "Requirement already satisfied: xxhash in /home/ml/anaconda3/envs/LLMs/lib/python3.10/site-packages (from datasets) (3.4.1)\n",
      "Requirement already satisfied: multiprocess in /home/ml/anaconda3/envs/LLMs/lib/python3.10/site-packages (from datasets) (0.70.15)\n",
      "Requirement already satisfied: fsspec[http]<=2023.10.0,>=2023.1.0 in /home/ml/anaconda3/envs/LLMs/lib/python3.10/site-packages (from datasets) (2023.9.0)\n",
      "Requirement already satisfied: aiohttp in /home/ml/anaconda3/envs/LLMs/lib/python3.10/site-packages (from datasets) (3.8.6)\n",
      "Requirement already satisfied: huggingface-hub<1.0.0,>=0.14.0 in /home/ml/anaconda3/envs/LLMs/lib/python3.10/site-packages (from datasets) (0.16.4)\n",
      "Requirement already satisfied: packaging in /home/ml/anaconda3/envs/LLMs/lib/python3.10/site-packages (from datasets) (23.1)\n",
      "Requirement already satisfied: pyyaml>=5.1 in /home/ml/anaconda3/envs/LLMs/lib/python3.10/site-packages (from datasets) (6.0.1)\n",
      "Requirement already satisfied: attrs>=17.3.0 in /home/ml/anaconda3/envs/LLMs/lib/python3.10/site-packages (from aiohttp->datasets) (23.1.0)\n",
      "Requirement already satisfied: charset-normalizer<4.0,>=2.0 in /home/ml/anaconda3/envs/LLMs/lib/python3.10/site-packages (from aiohttp->datasets) (3.2.0)\n",
      "Requirement already satisfied: multidict<7.0,>=4.5 in /home/ml/anaconda3/envs/LLMs/lib/python3.10/site-packages (from aiohttp->datasets) (6.0.4)\n",
      "Requirement already satisfied: async-timeout<5.0,>=4.0.0a3 in /home/ml/anaconda3/envs/LLMs/lib/python3.10/site-packages (from aiohttp->datasets) (4.0.3)\n",
      "Requirement already satisfied: yarl<2.0,>=1.0 in /home/ml/anaconda3/envs/LLMs/lib/python3.10/site-packages (from aiohttp->datasets) (1.9.2)\n",
      "Requirement already satisfied: frozenlist>=1.1.1 in /home/ml/anaconda3/envs/LLMs/lib/python3.10/site-packages (from aiohttp->datasets) (1.4.0)\n",
      "Requirement already satisfied: aiosignal>=1.1.2 in /home/ml/anaconda3/envs/LLMs/lib/python3.10/site-packages (from aiohttp->datasets) (1.3.1)\n",
      "Requirement already satisfied: filelock in /home/ml/anaconda3/envs/LLMs/lib/python3.10/site-packages (from huggingface-hub<1.0.0,>=0.14.0->datasets) (3.9.0)\n",
      "Requirement already satisfied: typing-extensions>=3.7.4.3 in /home/ml/anaconda3/envs/LLMs/lib/python3.10/site-packages (from huggingface-hub<1.0.0,>=0.14.0->datasets) (4.4.0)\n",
      "Requirement already satisfied: idna<4,>=2.5 in /home/ml/anaconda3/envs/LLMs/lib/python3.10/site-packages (from requests>=2.19.0->datasets) (3.4)\n",
      "Requirement already satisfied: urllib3<3,>=1.21.1 in /home/ml/anaconda3/envs/LLMs/lib/python3.10/site-packages (from requests>=2.19.0->datasets) (2.0.4)\n",
      "Requirement already satisfied: certifi>=2017.4.17 in /home/ml/anaconda3/envs/LLMs/lib/python3.10/site-packages (from requests>=2.19.0->datasets) (2023.7.22)\n",
      "Requirement already satisfied: python-dateutil>=2.8.1 in /home/ml/anaconda3/envs/LLMs/lib/python3.10/site-packages (from pandas->datasets) (2.8.2)\n",
      "Requirement already satisfied: pytz>=2020.1 in /home/ml/anaconda3/envs/LLMs/lib/python3.10/site-packages (from pandas->datasets) (2023.3.post1)\n"
     ]
    }
   ],
   "source": [
    "!pip install transformers==4.27.1\n",
    "!pip install rouge_chinese nltk jieba datasets"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "483082d1-d2c9-4315-a747-c3b678418129",
   "metadata": {},
   "outputs": [],
   "source": [
    "!cd ChatGLM2-6B && pip install -r requirements.txt"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e0d41ac9-45fc-4a97-aeaf-a3b7c583f99a",
   "metadata": {},
   "source": [
    "#### 文件修改"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "7256aafd-e57f-4878-8a3b-b4abd3abdfc0",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 修改 ./ptuning/train.sh\n",
    "\n",
    "PRE_SEQ_LEN=32\n",
    "LR=2e-2\n",
    "NUM_GPUS=1\n",
    "\n",
    "torchrun --standalone --nnodes=1 --nproc-per-node=$NUM_GPUS main.py \\\n",
    "    --do_train \\\n",
    "    --train_file AdvertiseGen/train.json \\\n",
    "    --validation_file AdvertiseGen/dev.json \\\n",
    "    --preprocessing_num_workers 10 \\\n",
    "    --prompt_column content \\\n",
    "    --response_column summary \\\n",
    "    --overwrite_cache \\\n",
    "    --model_name_or_path '/home/ml/PycharmProjects/LLMs/language/ChatGLM2-6B/weights' \\\n",
    "    --output_dir output/adgen-chatglm2-6b-pt-$PRE_SEQ_LEN-$LR \\\n",
    "    --overwrite_output_dir \\\n",
    "    --max_source_length 128 \\\n",
    "    --max_target_length 128 \\\n",
    "    --per_device_train_batch_size 1 \\\n",
    "    --per_device_eval_batch_size 1 \\\n",
    "    --gradient_accumulation_steps 16 \\\n",
    "    --predict_with_generate \\\n",
    "    --max_steps 3000 \\\n",
    "    --logging_steps 10 \\\n",
    "    --save_steps 1000 \\\n",
    "    --learning_rate $LR \\\n",
    "    --pre_seq_len $PRE_SEQ_LEN"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "95e50e4e-778f-425a-ba7e-d2e394165dc0",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 修改 ./ptuning/evaluate.sh\n",
    "\n",
    "PRE_SEQ_LEN=32\n",
    "CHECKPOINT=adgen-chatglm2-6b-pt-128-2e-2\n",
    "STEP=3000\n",
    "NUM_GPUS=1\n",
    "\n",
    "torchrun --standalone --nnodes=1 --nproc-per-node=$NUM_GPUS main.py \\\n",
    "    --do_predict \\\n",
    "    --validation_file AdvertiseGen/dev.json \\\n",
    "    --test_file AdvertiseGen/dev.json \\\n",
    "    --overwrite_cache \\\n",
    "    --prompt_column content \\\n",
    "    --response_column summary \\\n",
    "    --model_name_or_path '/home/ml/PycharmProjects/LLMs/language/ChatGLM2-6B/weights' \\\n",
    "    --ptuning_checkpoint ./output/$CHECKPOINT/checkpoint-$STEP \\\n",
    "    --output_dir ./output/$CHECKPOINT \\\n",
    "    --overwrite_output_dir \\\n",
    "    --max_source_length 128 \\\n",
    "    --max_target_length 128 \\\n",
    "    --per_device_eval_batch_size 1 \\\n",
    "    --predict_with_generate \\\n",
    "    --pre_seq_len $PRE_SEQ_LEN \\\n",
    "    --quantization_bit 4"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "2d3d5f38-2179-4749-86af-5f42676ab97c",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "c16cc92a-171d-4c6e-948d-e8a71e749691",
   "metadata": {},
   "source": [
    "#### 数据准备"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "d4c8fcfc-dcb9-44f5-8d8f-2a772aa9f6f4",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 广告词生成\n",
    "!mkdir ./ptuning/adgen && cd ./ptuning/adgen\n",
    "!wget https://huggingface.co/datasets/shibing624/AdvertiseGen/resolve/main/dev.json?download=true\n",
    "!wget https://huggingface.co/datasets/shibing624/AdvertiseGen/blob/main/train.json?download=true"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "086148d1-c327-4d9c-8c31-09dcd08d1049",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "48cadcf5-c0fd-47c9-873f-84279eaa41c1",
   "metadata": {},
   "source": [
    "#### 微调作业"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "746b38b2-2d73-459c-8aeb-8ad93ef7a30a",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 微调\n",
    "!bash train.sh"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "5589f01f-2ed7-42bb-9367-4cd9bdcf720e",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 验证\n",
    "!bash evaluate.sh"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "90066644-b99c-4be7-a0b0-76aea29a8edf",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "66fa9ad4-dc4a-49a7-a9df-167be747946f",
   "metadata": {},
   "source": [
    "#### 微调前"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "3b471af9-3879-4afc-9429-0adc8aa492f3",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Explicitly passing a `revision` is encouraged when loading a model with custom code to ensure no malicious code has been contributed in a newer revision.\n",
      "Explicitly passing a `revision` is encouraged when loading a configuration with custom code to ensure no malicious code has been contributed in a newer revision.\n",
      "Explicitly passing a `revision` is encouraged when loading a model with custom code to ensure no malicious code has been contributed in a newer revision.\n"
     ]
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "3c5814039c454124a963b4e223985023",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "Loading checkpoint shards:   0%|          | 0/7 [00:00<?, ?it/s]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "import os \n",
    "import torch\n",
    "from transformers import AutoTokenizer, AutoModel, AutoConfig\n",
    "\n",
    "\n",
    "MODEL_PATH = \"/home/ml/PycharmProjects/LLMs/language/ChatGLM2-6B/weights/\"\n",
    " \n",
    "tokenizer = AutoTokenizer.from_pretrained(MODEL_PATH, trust_remote_code=True)\n",
    "model = AutoModel.from_pretrained(MODEL_PATH, trust_remote_code=True).half().cuda()\n",
    "\n",
    "model = model.eval()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "427ac899-9d92-4dc5-9e98-630572d58ee4",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "你好👋！我是人工智能助手 ChatGLM2-6B，很高兴见到你，欢迎问我任何问题。\n"
     ]
    }
   ],
   "source": [
    "response, history = model.chat(tokenizer, \"你好\", history=[])\n",
    "print(response)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "cfab7aeb-7f7c-4e0d-93e1-aeb03a08ac57",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "简约印花撞色裙，优雅文艺风，修身显瘦，柔软舒适，气质优雅，设计独特，穿着舒适，优雅清新，凸显气质，设计别致，时尚潮流，优雅简约，清新自然，流畅线条，舒适面料，修身剪裁，衬托完美身材，美丽清新，自然舒适。\n"
     ]
    }
   ],
   "source": [
    "response, history = model.chat(tokenizer, \"类型#裙版型#显瘦风格#文艺风格#简约图案#印花图案#撞色裙下摆#压褶裙长#连衣裙裙领型#圆领\", history=[])\n",
    "print(response)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "862d2a7d-a9bd-45f3-adce-8359ea1c3582",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "这是一些关于衣服的信息,其中包含了一些与衣服相关的词汇,以及一些描述性词汇,如材质、颜色、风格、图案、衣样式和衣款式等。\n",
      "\n",
      "- 上衣:指衣服的上半部分,通常是由布料或纤维制成的。\n",
      "- 材质:指衣服所使用的材料,如牛仔布、棉布、丝绸等。\n",
      "- 颜色:指衣服的颜色,如白色、黑色、蓝色等。\n",
      "- 风格:指衣服的样式,如简约、休闲、正式等。\n",
      "- 图案:指衣服上的花纹或图案,如刺绣、织物图案等。\n",
      "- 衣样式:指衣服的款式,如宽松、修身、短袖等。\n",
      "- 衣款式:指衣服的样式,如连身、半身、长裙等。\n",
      "- 破洞:指衣服上的破洞或缝补处。\n"
     ]
    }
   ],
   "source": [
    "response, history = model.chat(tokenizer, \"类类型#上衣*材质#牛仔布*颜色#白色*风格#简约*图案#刺绣*衣样式#外套*衣款式#破洞\", history=[])\n",
    "print(response)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "e238fc03-324c-4b3a-bf6a-a7ceaba3d0d1",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Mon Nov 13 20:59:30 2023       \n",
      "+---------------------------------------------------------------------------------------+\n",
      "| NVIDIA-SMI 535.98                 Driver Version: 535.98       CUDA Version: 12.2     |\n",
      "|-----------------------------------------+----------------------+----------------------+\n",
      "| GPU  Name                 Persistence-M | Bus-Id        Disp.A | Volatile Uncorr. ECC |\n",
      "| Fan  Temp   Perf          Pwr:Usage/Cap |         Memory-Usage | GPU-Util  Compute M. |\n",
      "|                                         |                      |               MIG M. |\n",
      "|=========================================+======================+======================|\n",
      "|   0  NVIDIA GeForce RTX 4090 ...    Off | 00000000:01:00.0 Off |                  N/A |\n",
      "| N/A   44C    P0             135W / 150W |  12549MiB / 16376MiB |     98%      Default |\n",
      "|                                         |                      |                  N/A |\n",
      "+-----------------------------------------+----------------------+----------------------+\n",
      "                                                                                         \n",
      "+---------------------------------------------------------------------------------------+\n",
      "| Processes:                                                                            |\n",
      "|  GPU   GI   CI        PID   Type   Process name                            GPU Memory |\n",
      "|        ID   ID                                                             Usage      |\n",
      "|=======================================================================================|\n",
      "|    0   N/A  N/A     21751      G   /usr/lib/xorg/Xorg                            4MiB |\n",
      "|    0   N/A  N/A     21972    C+G   ...libexec/gnome-remote-desktop-daemon      239MiB |\n",
      "|    0   N/A  N/A    859627      C   ...e/ml/anaconda3/envs/LLMs/bin/python    12288MiB |\n",
      "+---------------------------------------------------------------------------------------+\n"
     ]
    }
   ],
   "source": [
    "!nvidia-smi"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "4c883419-cdf6-463f-a2a7-ef05665c706b",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "a65acc7c-fb12-4237-80a3-d28f4e53c304",
   "metadata": {},
   "source": [
    "#### 微调后"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "ffd62a68-5d37-4273-a080-43b053808ad7",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Explicitly passing a `revision` is encouraged when loading a configuration with custom code to ensure no malicious code has been contributed in a newer revision.\n",
      "Explicitly passing a `revision` is encouraged when loading a model with custom code to ensure no malicious code has been contributed in a newer revision.\n",
      "Explicitly passing a `revision` is encouraged when loading a model with custom code to ensure no malicious code has been contributed in a newer revision.\n"
     ]
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "3d35673015e047f6bf7da534e1526bbb",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "Loading checkpoint shards:   0%|          | 0/7 [00:00<?, ?it/s]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Some weights of ChatGLMForConditionalGeneration were not initialized from the model checkpoint at /home/ml/PycharmProjects/LLMs/language/ChatGLM2-6B/weights/ and are newly initialized: ['transformer.prefix_encoder.embedding.weight']\n",
      "You should probably TRAIN this model on a down-stream task to be able to use it for predictions and inference.\n"
     ]
    }
   ],
   "source": [
    "import os \n",
    "import torch\n",
    "from transformers import AutoTokenizer, AutoModel, AutoConfig\n",
    "\n",
    "\n",
    "MODEL_PATH = \"/home/ml/PycharmProjects/LLMs/language/ChatGLM2-6B/weights/\"\n",
    "CHECKPOINT_PATH = \"/home/ml/PycharmProjects/LLMs/language/ChatGLM2-6B/ptuning/output/adgen-chatglm2-6b-pt-32-2e-2/checkpoint-3000/\"\n",
    " \n",
    "\n",
    "config = AutoConfig.from_pretrained(MODEL_PATH, trust_remote_code=True, pre_seq_len=32)\n",
    "tokenizer = AutoTokenizer.from_pretrained(MODEL_PATH, trust_remote_code=True)\n",
    "model = AutoModel.from_pretrained(MODEL_PATH, trust_remote_code=True, config=config).half().cuda()\n",
    "\n",
    "prefix_state_dict = torch.load(os.path.join(CHECKPOINT_PATH, \"pytorch_model.bin\"))\n",
    "new_prefix_state_dict = {}\n",
    "\n",
    "for k, v in prefix_state_dict.items():\n",
    "    if k.startswith(\"transformer.prefix_encoder.\"):\n",
    "        new_prefix_state_dict[k[len(\"transformer.prefix_encoder.\"):]] = v\n",
    "model.transformer.prefix_encoder.load_state_dict(new_prefix_state_dict)\n",
    "\n",
    "model = model.eval()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "6d7ed338-6dde-4e56-8f4b-d1de2eb7e11c",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "这款裙子采用经典的半裙款式，不仅穿着舒适，而且设计感十足。同时，裙子的裙摆采用前短后长的设计，能够有效的拉长腿部线条，让你拥有大长腿的迷人气质。\n"
     ]
    }
   ],
   "source": [
    "response, history = model.chat(tokenizer, \"你好\", history=[])\n",
    "print(response)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "1727147e-1172-4b38-8403-151f32ac9ac0",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "这款连衣裙整体的设计简约大气，穿着舒适，修饰身材。圆领的设计，修饰脖颈，显瘦显高。撞色的印花图案，彰显文艺风，凸显女性气质。腰部压褶的设计，凸显腰身，修身显瘦。\n"
     ]
    }
   ],
   "source": [
    "response, history = model.chat(tokenizer, \"类型#裙版型#显瘦风格#文艺风格#简约图案#印花图案#撞色裙下摆#压褶裙长#连衣裙裙领型#圆领\", history=[])\n",
    "print(response)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "61fc23aa-62a9-4eb8-a6f6-55c52d8c1c74",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "这款牛仔外套采用经典百搭的牛仔面料，上身舒适自然，穿着更加耐磨耐用。袖口和领口采用简约的白色刺绣装饰，衬托出整体的时尚感。胸前采用破洞设计，更加有层次感。\n"
     ]
    }
   ],
   "source": [
    "response, history = model.chat(tokenizer, \"类类型#上衣*材质#牛仔布*颜色#白色*风格#简约*图案#刺绣*衣样式#外套*衣款式#破洞\", history=[])\n",
    "print(response)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "f0af67fc-811d-433c-b2db-105b14ba6735",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Mon Nov 13 21:00:35 2023       \n",
      "+---------------------------------------------------------------------------------------+\n",
      "| NVIDIA-SMI 535.98                 Driver Version: 535.98       CUDA Version: 12.2     |\n",
      "|-----------------------------------------+----------------------+----------------------+\n",
      "| GPU  Name                 Persistence-M | Bus-Id        Disp.A | Volatile Uncorr. ECC |\n",
      "| Fan  Temp   Perf          Pwr:Usage/Cap |         Memory-Usage | GPU-Util  Compute M. |\n",
      "|                                         |                      |               MIG M. |\n",
      "|=========================================+======================+======================|\n",
      "|   0  NVIDIA GeForce RTX 4090 ...    Off | 00000000:01:00.0 Off |                  N/A |\n",
      "| N/A   46C    P0             136W / 150W |  12539MiB / 16376MiB |     85%      Default |\n",
      "|                                         |                      |                  N/A |\n",
      "+-----------------------------------------+----------------------+----------------------+\n",
      "                                                                                         \n",
      "+---------------------------------------------------------------------------------------+\n",
      "| Processes:                                                                            |\n",
      "|  GPU   GI   CI        PID   Type   Process name                            GPU Memory |\n",
      "|        ID   ID                                                             Usage      |\n",
      "|=======================================================================================|\n",
      "|    0   N/A  N/A     21751      G   /usr/lib/xorg/Xorg                            4MiB |\n",
      "|    0   N/A  N/A     21972    C+G   ...libexec/gnome-remote-desktop-daemon      239MiB |\n",
      "|    0   N/A  N/A    859921      C   ...e/ml/anaconda3/envs/LLMs/bin/python    12278MiB |\n",
      "+---------------------------------------------------------------------------------------+\n"
     ]
    }
   ],
   "source": [
    "!nvidia-smi"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "2bdfe851-0f24-4dfc-9c4a-1db10ed477e0",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "4e4059e8-9c77-4e70-9cce-fa12213bdc6b",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "266bb326-d9e1-4751-b10b-af4edbd4bf2b",
   "metadata": {},
   "source": [
    "### 实战 3 - ChatGLM3 Fine-Tuning (LoRA)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "fa04c2af-814a-4982-8794-0530394c8bad",
   "metadata": {},
   "outputs": [],
   "source": [
    "# LLaMA-Factory (用 UI 的方式来进行微调模型)\n",
    "# https://github.com/hiyouga/LLaMA-Factory"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "08142ef6-3e3a-4814-8c22-ae177dfca8f7",
   "metadata": {},
   "outputs": [],
   "source": [
    "# LoRA & QLoRA "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "c3abf671-56dd-42ee-b1c2-74665adf9930",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 原始模型权重的推理\n",
    "# /home/ml/PycharmProjects/LLMs/language/ChatGLM3/web_demo.py"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "edb23d65-e2b9-4b0b-8135-bccd31d80ab7",
   "metadata": {},
   "source": [
    "![ChatGLM3_Standard](./resource/images/ChatGLM3_Standard.png)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "e9923e06-f74a-46a0-a53a-8c45f3b61c22",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 实操微调 \n",
    "# 微调后推理\n",
    "# /home/ml/PycharmProjects/LLMs/language/LLaMA-Factory/src/train_web.py"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a7853a60-2a2b-409f-b886-bddca15c972a",
   "metadata": {},
   "source": [
    "![ChatGLM3_Fine-Tuning](./resource/images/ChatGLM3_Fine-Tuning.png)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "d524eb00-e839-4d65-9b7c-0bbc5183a50f",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "104ea6d2-0401-4bbb-a200-9870b673dec0",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "975fff04-ca67-4c3d-aa75-7539ae971005",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "53da9663-5810-42e3-bb18-2ebf618e7366",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "476721ef-5955-46b1-bc09-91a10629696f",
   "metadata": {},
   "source": [
    "### 总结和回顾"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "2eb1175c-0acf-4515-9928-383fa2ddf45e",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "64755092-ec18-4c33-8059-9da448b9e42b",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "c2539c80-67ff-4835-ab2c-7d6bff286da6",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "eb97e0b3-2527-4fa9-9095-1d19cb713ae1",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "f6fb9bea-8519-4ae6-8eb0-62c73ba3dad7",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "1596b7ac-33f6-4ed5-9d15-ccc095998c13",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "f71515d7-a8c0-41d2-bb8d-744a3e8d19a3",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "7d87f69a-c06f-405a-863a-d0d3a3319ec3",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
